「サンプルプログラム集」の版間の差分

提供: Wikinote
移動: 案内検索
(dec2bin.py)
(ToggleDisplay から mw-collapsible に変更)
 
(同じ利用者による、間の12版が非表示)
行1: 行1:
 +
TP の素を揃えておこうかと。
 +
 
== C ==
 
== C ==
 +
 +
=== pthread.c ===
 +
 +
コマンド引き数で与えられた数だけ、ただ寝てるだけのスレッドを生成するプログラム。
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
ソースコード
 +
<div class="mw-collapsible-content">
 +
#include <stdio.h>
 +
#include <stdlib.h>
 +
#include <pthread.h>
 +
 +
void *thread_func(void *arg) {
 +
    printf("Thread %d\n", (int) arg);
 +
    while (1)
 +
        sleep(1);
 +
}
 +
int main(int argc, char *argv[]) {
 +
    int i, num;
 +
    pthread_t *th;
 +
 +
    if (argc < 2) {
 +
        printf("Usage: %s threads\n", argv[0]);
 +
        return 1;
 +
    }
 +
    if ((num = atoi(argv[1])) < 1) {
 +
        printf("arg 1 = %d\n", num);
 +
        return 1;
 +
    }
 +
    th = (pthread_t *) malloc(sizeof(pthread_t) * num);
 +
    for (i = 0; i < num; i++) {
 +
        pthread_create(&th[i], NULL, &thread_func, (void *) i);
 +
    }
 +
    for (i = 0; i < num; i++) {
 +
        pthread_join(th[i], NULL);
 +
    }
 +
    return 0;
 +
}
 +
</div></div>
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 +
$ cc -l pthread -o pthread pthread.c
 +
$ ./pthread
 +
Usage: ./pthread threads
 +
$ ./pthread 3 &
 +
[1] 580
 +
Thread 0
 +
Thread 1
 +
Thread 2
 +
$ ps -elfL | grep pthread
 +
0 S hagio      580 13327  580  0    4  77  0 -  8117 -      09:59 pts/5    00:00:00 ./pthread 3
 +
1 S hagio      580 13327  582  0    4  75  0 -  8117 -      09:59 pts/5    00:00:00 ./pthread 3
 +
1 S hagio      580 13327  583  0    4  75  0 -  8117 -      09:59 pts/5    00:00:00 ./pthread 3
 +
1 S hagio      580 13327  584  0    4  75  0 -  8117 -      09:59 pts/5    00:00:00 ./pthread 3
 +
0 S hagio      602 13327  602  0    1  77  0 -  1245 pipe_w 09:59 pts/5    00:00:00 grep pthread
 +
$ kill $!
 +
[1]+  終了しました      ./pthread 3
 +
</div></div>
 +
 +
=== fork.c ===
 +
 +
コマンド引き数で与えられた数だけ fork して、ゾンビ状態で放置するプログラム。
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
ソースコード
 +
<div class="mw-collapsible-content">
 +
#include <stdio.h>
 +
#include <unistd.h>
 +
#include <sys/types.h>
 +
 +
int main(int argc, char *argv[]) {
 +
    int i, num;
 +
    pid_t pid;
 +
 +
    if (argc < 2) {
 +
        printf("Usage %s procs\n", argv[0]);
 +
        return 0;
 +
    }
 +
    if ((num = atoi(argv[1])) < 0) {
 +
        printf("arg 1 = %d\n", num);
 +
        return 0;
 +
    }
 +
    for (i = 0; i < num; i++) {
 +
        pid = fork();
 +
        if (pid < 0) {
 +
            perror("fork");
 +
            return 1;
 +
        } else if (pid == 0) {
 +
            printf("Child %d\n", i);
 +
            //while (1) sleep(1);
 +
            return 0;
 +
        } else {
 +
            printf("Parent %d (PID: %d)\n", i, pid);
 +
        }
 +
    }
 +
    while (1) sleep(1);
 +
    return 0;
 +
}
 +
</div></div>
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 +
$ cc -o fork fork.c
 +
$ ./fork 3
 +
Child 0
 +
Parent 0 (PID: 1197)
 +
Child 1
 +
Parent 1 (PID: 1198)
 +
Child 2
 +
Parent 2 (PID: 1199)
 +
$ ps -elf | grep fork
 +
0 S hagio    1196 13327  0  75  0 -  378 -      10:30 pts/5    00:00:00 ./fork 3
 +
1 Z hagio    1197  1196  0  76  0 -    0 exit  10:30 pts/5    00:00:00 [fork] <defunct>
 +
1 Z hagio    1198  1196  0  77  0 -    0 exit  10:30 pts/5    00:00:00 [fork] <defunct>
 +
1 Z hagio    1199  1196  0  77  0 -    0 exit  10:30 pts/5    00:00:00 [fork] <defunct>
 +
0 S hagio    1208 31213  0  78  0 -  1245 pipe_w 10:30 pts/4    00:00:00 grep fork
 +
</div></div>
 +
 +
=== setro.c ===
 +
 +
ioctl のサンプル。ブロックデバイスの読み込み専用フラグを変更するプログラム。
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
ソースコード
 +
<div class="mw-collapsible-content">
 +
#include <stdio.h>
 +
#include <fcntl.h>
 +
#include <linux/fs.h>
 +
 +
int main(int argc, char* argv[]) {
 +
    int fd, res, flag;
 +
 +
    if (argc != 3) {
 +
        printf("Usage: %s DEVICE RO_FLAG\n", argv[0]);
 +
        return 1;
 +
    }
 +
 +
    if ((fd = open(argv[1], O_RDWR)) < 0) {
 +
        perror("open");
 +
        return 1;
 +
    }
 +
 +
    flag = atoi(argv[2]);
 +
    if ((res = ioctl(fd, BLKROSET, &flag)) < 0) {
 +
        perror("ioctl");
 +
        close(fd);
 +
        return 1;
 +
    }
 +
    close(fd);
 +
    return 0;
 +
}
 +
</div></div>
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 +
# umount /boot        ★いったんアンマウント
 +
# ./setro /dev/sda1 1 ★リードオンリーにセット
 +
# mount /boot
 +
mount: ブロックデバイス /dev/sda1 は書き込み禁止です、読込み専用でマウントします
 +
# umount /boot
 +
# ./setro /dev/sda1 0 ★リードオンリーを解除
 +
# mount /boot
 +
</div></div>
 +
 +
=== signal.c ===
 +
 +
単に受信したシグナル番号を出力するプログラム。
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
ソースコード
 +
<div class="mw-collapsible-content">
 +
#include <stdio.h>
 +
#include <signal.h>
 +
 +
void signal_handler(int sig) {
 +
    printf("signal: %d\n", sig);
 +
}
 +
int main(void) {
 +
    //signal(SIGINT , SIG_IGN);
 +
    signal(SIGINT , SIG_DFL);
 +
    signal(SIGQUIT, signal_handler);
 +
    signal(SIGALRM, signal_handler);
 +
    signal(SIGTERM, signal_handler);
 +
    alarm(5);
 +
    while (1) {
 +
        sleep(1);
 +
    }
 +
}
 +
</div></div>
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 +
$ ./signal
 +
signal: 3
 +
signal: 3
 +
signal: 15
 +
signal: 14
 +
signal: 3
 +
</div></div>
 +
 +
=== shm.c ===
 +
 +
共有メモリの確保と読み書きを行うプログラム。削除は ipcrm で…。
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
ソースコード
 +
<div class="mw-collapsible-content">
 +
#include <stdio.h>
 +
#include <sys/ipc.h>
 +
#include <sys/shm.h>
 +
#include <string.h>
 +
 +
#define SHM_SIZE 1024
 +
 +
int main(int argc, char *argv[]) {
 +
    int shmid;
 +
    char *shmaddr;
 +
    char *data;
 +
 +
    if (argc < 2) {
 +
        printf("Usage: %s data [shmid]\n", argv[0]);
 +
        return 1;
 +
    }
 +
    data = argv[1];
 +
    if (argc < 3) {
 +
        if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0666)) < 0) {
 +
            perror("shmget");
 +
            return 1;
 +
        }
 +
        printf("new shmid = %d\n", shmid);
 +
    } else {
 +
        shmid = atoi(argv[2]);
 +
    }
 +
 +
    if ((shmaddr = shmat(shmid, NULL, 0)) < 0) {
 +
        perror("shmat");
 +
        return 1;
 +
    }
 +
    printf("shmaddr = %p\n", shmaddr);
 +
    printf("current value = %s\n", shmaddr);
 +
 +
    strcpy(shmaddr, data);
 +
    printf("written value = %s\n", shmaddr);
 +
}
 +
</div></div>
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 +
$ ./a.out
 +
Usage: ./a.out data [shmid]
 +
$ ./a.out "test data"
 +
new shmid = 655367
 +
shmaddr = 0xb7fb1000
 +
current value =
 +
written value = test data
 +
$ ./a.out hoge 655367
 +
shmaddr = 0xb7f27000
 +
current value = test data
 +
written value = hoge
 +
$ ./a.out test 655367
 +
shmaddr = 0xb7fb2000
 +
current value = hoge
 +
written value = test
 +
$ ipcs -m
 +
 +
------ 共有メモリセグメント --------
 +
キー    shmid      所有者  権限    バイト  nattch    状態     
 +
0x00000000 229379    hagio    600        393216    2          対象     
 +
0x00000000 262149    hagio    600        393216    2          対象     
 +
0x00000000 655367    hagio    666        1024      0                     
 +
 +
$ ipcrm -m 655367
 +
$ ipcs -m
 +
 +
------ 共有メモリセグメント --------
 +
キー    shmid      所有者  権限    バイト  nattch    状態     
 +
0x00000000 229379    hagio    600        393216    2          対象     
 +
0x00000000 262149    hagio    600        393216    2          対象     
 +
 +
</div></div>
  
 
== Python ==
 
== Python ==
 +
 +
=== tcp_server.py / tcp_client.py ===
 +
 +
簡単な TCP サーバ / クライアントプログラム。例外処理はある程度まで。
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
tcp_server.py
 +
<div class="mw-collapsible-content">
 +
#!/usr/bin/env python
 +
import sys, socket
 +
 +
port = 55555
 +
if len(sys.argv) > 1:
 +
    try:
 +
        port = int(sys.argv[1])
 +
    except:
 +
        print "Ivalid port number"
 +
        sys.exit(1)
 +
 +
try:
 +
    sock = socket.socket()
 +
    sock.bind(("", port))
 +
    sock.listen(5)
 +
except socket.error, msg:
 +
    print msg
 +
    sys.exit(1)
 +
   
 +
while True:
 +
    print "Waiting for a connection (port: %d)..." % port
 +
    try:
 +
        csock, addr = sock.accept()
 +
        print "Connected by %s:%d" % addr
 +
        while True:
 +
            try:
 +
                buf = csock.recv(1024)
 +
                if not buf:
 +
                    print "Disconnected."
 +
                    break
 +
                print "Received : %s" % buf
 +
            except KeyboardInterrupt:
 +
                break
 +
        csock.close()
 +
    except KeyboardInterrupt:
 +
        break
 +
sock.close()
 +
</div></div>
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
tcp_client.py
 +
<div class="mw-collapsible-content">
 +
#!/usr/bin/env python
 +
import sys, socket
 +
 +
if len(sys.argv) < 2:
 +
    print "Usage: %s host [port]" % sys.argv[0]
 +
    sys.exit(1)
 +
 +
host = sys.argv[1]
 +
port = 55555
 +
if len(sys.argv) > 2:
 +
    try:
 +
        port = int(sys.argv[2])
 +
    except ValueError:
 +
        print "Invalid port number"
 +
        sys.exit(1)
 +
 +
try:
 +
    sock = socket.socket()
 +
    sock.connect((host, port))
 +
except socket.error, msg:
 +
    print msg
 +
    sys.exit(1)
 +
print "Connected to %s:%d" % (host, port)
 +
while True:
 +
    try:
 +
        buf = raw_input("> ")
 +
        if buf == "q":
 +
            break
 +
        sock.send(buf)
 +
    except KeyboardInterrupt:
 +
        break
 +
sock.close()
 +
</div></div>
 +
 +
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 +
サーバ側:
 +
$ ./tcp_server.py 12345
 +
Waiting for a connection (port: 12345)...
 +
Connected by 127.0.0.1:51522
 +
Received : test data
 +
Disconnected.
 +
Waiting for a connection (port: 12345)...
 +
 +
クライアント側:
 +
$ ./tcp_client.py localhost 12345
 +
Connected to localhost:12345
 +
> test data
 +
>
 +
> quit
 +
</div></div>
  
 
=== memcurses.py ===
 
=== memcurses.py ===
行7: 行397:
 
curses (libcurses) を利用した /proc/meminfo の変化量を表示するスクリプト。
 
curses (libcurses) を利用した /proc/meminfo の変化量を表示するスクリプト。
  
ソースコード <toggledisplay>
+
<div class="mw-collapsible mw-collapsed">
 +
ソースコード
 +
<div class="mw-collapsible-content">
 
  #!/usr/bin/env python
 
  #!/usr/bin/env python
 
  import sys, time, curses
 
  import sys, time, curses
行48: 行440:
 
  if __name__ == "__main__":
 
  if __name__ == "__main__":
 
     sys.exit(main(sys.argv))
 
     sys.exit(main(sys.argv))
</toggledisplay>
+
</div></div>
  
実行例 <toggledisplay>
+
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 
  $ ./memcurses.py 5
 
  $ ./memcurses.py 5
 
  Every 5.0s : Sat Feb 26 01:06:31 2011
 
  Every 5.0s : Sat Feb 26 01:06:31 2011
行84: 行478:
 
  HugePages_Rsvd:      0
 
  HugePages_Rsvd:      0
 
  Hugepagesize:    2048 kB
 
  Hugepagesize:    2048 kB
</toggledisplay>
+
</div></div>
 +
 
 +
=== grep.py ===
 +
 
 +
<code>grep -Hn</code> と同様の出力となるスクリプト。
 +
標準入力からの入力には非対応。
 +
 
 +
<div class="mw-collapsible mw-collapsed">
 +
ソースコード
 +
<div class="mw-collapsible-content">
 +
#!/usr/bin/env python
 +
import sys, re, threading
 +
 +
def grep(reg, path):
 +
    f = open(path, "r")
 +
    row = 1
 +
    for line in f:
 +
        if reg.search(line):
 +
            print "%s:%d:%s" % (path, row, line),
 +
        row += 1
 +
    f.close()
 +
 +
if __name__ == "__main__":
 +
    if len(sys.argv) > 2:
 +
        reg = re.compile(sys.argv[1])
 +
        for path in sys.argv[2:]:
 +
            grep(reg, path)
 +
    else:
 +
        print "Usage: %s PATTERN FILES.." % sys.argv[0]
 +
        sys.exit(1)
 +
</div></div>
 +
 
 +
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 +
$ ./grep.py
 +
Usage: ./grep.py PATTERN FILES..
 +
$ ./grep.py while *.py
 +
graph.py:9:    while 1:
 +
memcurses.py:13:    while True:
 +
memstat.py:12:    while True:
 +
ncurses.py:8:    while True:
 +
netmonitor.py:32:    while 1:
 +
netstat.py:67:        while True:
 +
netstat.py:132:while True:
 +
open.py:12:while True:
 +
pystat.py:85:while True:
 +
sdx.py:9:    while (q > 0):
 +
tcp_client.py:13:while True:
 +
tcp_server.py:8:while 1:
 +
tcp_server.py:13:        while True:
 +
</div></div>
 +
 
 +
=== wc.py ===
 +
 
 +
Python で作った wc コマンド。
 +
 
 +
<div class="mw-collapsible mw-collapsed">
 +
ソースコード
 +
<div class="mw-collapsible-content">
 +
#!/usr/bin/env python
 +
import sys, getopt
 +
 +
def usage():
 +
    print "Usage: %s [-cmlLw] FILES" % sys.argv[0]
 +
 +
def wc(f):
 +
    (c, m, l, L, w) = (0, 0, 0, 0, 0)
 +
    for line in f:
 +
        c += len(line)
 +
        m += len(line.decode('UTF-8'))
 +
        l += 1
 +
        L  = max(L, len(line)-1)
 +
        w += len(line.split())
 +
    return (c, m, l, L, w)
 +
 +
if __name__ == "__main__":
 +
    try:
 +
        opts, args = getopt.getopt(sys.argv[1:], "cmlLw")
 +
    except getopt.GetoptError:
 +
        usage()
 +
        sys.exit(1)
 +
 +
    # set defaults
 +
    opt_c = True  # bytes
 +
    opt_m = False # chars
 +
    opt_l = True  # lines
 +
    opt_L = False # max-line-length
 +
    opt_w = True  # words
 +
 +
    if opts:
 +
        (opt_c, opt_l, opt_w) = (False, False, False)
 +
    for (opt, val) in opts:
 +
        if opt == "-c":
 +
            opt_c = True
 +
        elif opt == "-m":
 +
            opt_m = True
 +
        elif opt == "-l":
 +
            opt_l = True
 +
        elif opt == "-L":
 +
            opt_L = True
 +
        elif opt == "-w":
 +
            opt_w = True
 +
 +
    (total_c, total_m, total_l, total_L, total_w) = (0, 0, 0, 0, 0)
 +
    if not args:
 +
        args.append("-")
 +
    for arg in args:
 +
        if arg == "-":
 +
            f = sys.stdin
 +
        else:
 +
            f = open(arg, "r")
 +
        (c, m, l, L, w) = wc(f)
 +
        f.close()
 +
        if opt_l:
 +
            print " %5d" % l,
 +
        if opt_w:
 +
            print " %5d" % w,
 +
        if opt_m:
 +
            print " %5d" % m,
 +
        if opt_c:
 +
            print " %5d" % c,
 +
        if opt_L:
 +
            print " %5d" % L,
 +
        print arg
 +
        total_c += c
 +
        total_m += m
 +
        total_l += l
 +
        total_L = max(total_L, L)
 +
        total_w += w
 +
 +
    if len(args) > 1:
 +
        if opt_l:
 +
            print " %5d" % total_l,
 +
        if opt_w:
 +
            print " %5d" % total_w,
 +
        if opt_m:
 +
            print " %5d" % total_m,
 +
        if opt_c:
 +
            print " %5d" % total_c,
 +
        if opt_L:
 +
            print " %5d" % total_L,
 +
        print "total"
 +
</div></div>
 +
 
 +
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 +
$ ./wc.py -h
 +
Usage: ./wc.py [-cmlLw] FILES
 +
$ ./wc.py -clmwL *.py | addspace
 +
    29    80    438    438    45 awk.py
 +
    28    82    719    719    59 buddy.py
 +
    23    70    531    531    65 calc_buddy.py
 +
      4    12    79    79    28 compare.py
 +
    21    55    444    444    43 dec2bin.py
 +
    35    98  1000  1000    49 decode_actlog.py
 +
    87    255  2287  2287    51 graph.py
 +
    20    58    475    475    55 grep.py
 +
    24    78    498    498    43 hex2bin.py
 +
    79    207  1790  1790    71 mail.py
 +
    127    347  3129  3129    109 mail2pens.py
 +
    40    91  1003  1003    71 memcurses.py
 +
    38    77    881    881    63 memstat.py
 +
    21    35    398    398    41 ncurses.py
 +
    54    134  1463  1463    101 netmonitor.py
 +
    144    590  4967  4967    129 netstat.py
 +
    19    30    246    246    40 open.py
 +
    33    105    916    916    57 pygrep.py
 +
    124    376  2977  2977    80 pystat.py
 +
    24    73    510    510    52 sdx.py
 +
    19    43    331    331    40 tcp_client.py
 +
    24    52    523    523    46 tcp_server.py
 +
    84    277  1983  1983    67 wc.py
 +
  1101  3225  27588  27588    129 total
 +
  lines  words  chars  bytes maxlen
 +
</div></div>
  
 
=== calc_buddy.py ===
 
=== calc_buddy.py ===
行91: 行661:
 
タイムスタンプを付けて記録したファイルにも対応。
 
タイムスタンプを付けて記録したファイルにも対応。
  
ソースコード <toggledisplay>
+
パイプで less などに繋いだ後に Broken Pipe のエラーが出ないように修正。
 +
 
 +
<div class="mw-collapsible mw-collapsed">
 +
ソースコード
 +
<div class="mw-collapsible-content">
 
  #!/usr/bin/env python
 
  #!/usr/bin/env python
 
  import sys
 
  import sys
行104: 行678:
 
  for file in files:
 
  for file in files:
 
     for line in file:
 
     for line in file:
         if len(line) &gt; 1:
+
         try:
            print line[:-1],
+
            if len(line) > 1:
            fields = line.split()
+
                print line[:-1],
            total = 0
+
                fields = line.split()
            for val in range(0,11):
+
                total = 0
                total += int(fields[ts_shift + val]) * 4 * 2**val
+
                for val in range(0,11):
            print total, "KB"
+
                    total += int(fields[ts_shift + val]) * 4 * 2**val
        else:
+
                print total, "KB"
            print line,
+
            else:
 +
                print line,
 +
        except IOError:
 +
            break
 
     file.close()
 
     file.close()
  </toggledisplay>
+
  </div></div>
  
実行例 <toggledisplay>
+
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 
  $ ./calc_buddy.py  
 
  $ ./calc_buddy.py  
 
  Node 0, zone      DMA    46      5      3      0      0      0      0      1      1      1      0  3856 KB
 
  Node 0, zone      DMA    46      5      3      0      0      0      0      1      1      1      0  3856 KB
 
  Node 0, zone  Normal    327      2      1      1      1      1      1      0      0      0      1  5916 KB
 
  Node 0, zone  Normal    327      2      1      1      1      1      1      0      0      0      1  5916 KB
 
  Node 0, zone  HighMem  78051  15607    279      2    59    17      2      0      0      0      0  448052 KB
 
  Node 0, zone  HighMem  78051  15607    279      2    59    17      2      0      0      0      0  448052 KB
</toggledisplay>
+
</div></div>
  
 
=== dec2bin.py ===
 
=== dec2bin.py ===
行127: 行706:
 
10 進数を 2 進数に変換するスクリプト。32 ビット限定。
 
10 進数を 2 進数に変換するスクリプト。32 ビット限定。
  
ソースコード <toggledisplay>
+
<div class="mw-collapsible mw-collapsed">
 +
ソースコード
 +
<div class="mw-collapsible-content">
 
  #!/usr/bin/env python
 
  #!/usr/bin/env python
 
  import sys
 
  import sys
行149: 行730:
 
         print "Invalid number"
 
         print "Invalid number"
 
         sys.exit(1)
 
         sys.exit(1)
</toggledisplay>
+
</div></div>
  
実行例 <toggledisplay>
+
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 +
$ ./dec2bin.py
 +
Usage: ./dec2bin.py dec
 
  $ ./dec2bin.py 12345
 
  $ ./dec2bin.py 12345
 
  11000000111001
 
  11000000111001
行159: 行744:
 
  11111111111111110000000000000000
 
  11111111111111110000000000000000
 
  $ ./dec2bin.py 2147483647
 
  $ ./dec2bin.py 2147483647
  1111111111111111111111111111111
+
  1111111111111111111111111111111 // 先頭の 0 は省かれている
 
  $ ./dec2bin.py -2147483648
 
  $ ./dec2bin.py -2147483648
 
  10000000000000000000000000000000
 
  10000000000000000000000000000000
</toggledisplay>
+
</div></div>
 +
 
 +
=== int2bin.py ===
 +
 
 +
上の dec2bin.py を利用して、8, 10, 16 進数に対応させたもの。
 +
コメントアウトしている最後の出力はビット位置確認用。
 +
 
 +
dec2bin の名前の付け方が悪かったな。
 +
 
 +
<div class="mw-collapsible mw-collapsed">
 +
ソースコード
 +
<div class="mw-collapsible-content">
 +
#!/usr/bin/env python
 +
import sys
 +
from dec2bin import dec2bin
 +
 +
def usage():
 +
    print "Usage: %s DEC|'0x'HEX|'0'OCT" % sys.argv[0]
 +
    sys.exit(1)
 +
 +
if __name__ == "__main__":
 +
    if len(sys.argv) < 2:
 +
        usage()
 +
    num = sys.argv[1]
 +
    try:
 +
        if num[:2] == "0x":
 +
            b = dec2bin(int(sys.argv[1], 16))
 +
        elif num[0] == "0":
 +
            b = dec2bin(int(sys.argv[1], 8))
 +
        else:
 +
            b = dec2bin(int(sys.argv[1], 10))
 +
    except ValueError:
 +
        usage()
 +
    l = len(b)
 +
    s = ''
 +
    for i in range(0, l, 1):
 +
        r = i % 4
 +
        s = str(2 ** r) + s
 +
    #print s
 +
    print b
 +
</div></div>
 +
 
 +
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 +
$ ./int2bin.py
 +
Usage: ./int2bin.py DEC|'0x'HEX|'0'OCT
 +
$ ./int2bin.py 255
 +
11111111
 +
$ ./int2bin.py -255
 +
11111111111111111111111100000001
 +
$ ./int2bin.py 0x12ab
 +
1001010101011
 +
$ ./int2bin.py 0xdeadbeef
 +
11011110101011011011111011101111
 +
$ ./int2bin.py 0755
 +
111101101
 +
</div></div>
 +
 
 +
== bash ==
 +
 
 +
=== cgrep ===
 +
 
 +
パターンが呼ばれている関数を検索するスクリプト。
 +
ほとんど awk だけど。
 +
 
 +
<div class="mw-collapsible mw-collapsed">
 +
スクリプト
 +
<div class="mw-collapsible-content">
 +
#!/bin/bash
 +
IFS=$'\n'
 +
RESULT=$(grep -nH $@)
 +
for l in $RESULT; do
 +
    FILE=$(echo "$l" | cut -d: -f 1)
 +
    LINE=$(echo "$l" | cut -d: -f 2)
 +
    gawk -v line=$LINE -v file=$FILE '
 +
        NR < line && /^\w/ && !/:/ {
 +
            cand = $0
 +
            cand_line = NR
 +
        }
 +
        NR == line {
 +
            if ($0 ~ /^\w/) {
 +
                print file ":" line ":"
 +
            } else {
 +
                print file ":" cand_line ":"
 +
                print cand
 +
            }
 +
            gsub("\t", "    ")
 +
            print $0
 +
            exit
 +
        }
 +
    ' $FILE
 +
done
 +
</div></div>
 +
 
 +
<div class="mw-collapsible mw-collapsed">
 +
実行例
 +
<div class="mw-collapsible-content">
 +
$ cgrep -r shrink_slab mm
 +
mm/vmscan.c:177:
 +
unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
 +
mm/vmscan.c:1026:
 +
unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask)
 +
        shrink_slab(sc.nr_scanned, gfp_mask, lru_pages);
 +
mm/vmscan.c:1134:
 +
static unsigned long balance_pgdat(pg_data_t *pgdat, int order)
 +
            nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
 +
mm/vmscan.c:1426:
 +
unsigned long shrink_all_memory(unsigned long nr_pages)
 +
        shrink_slab(nr_pages, sc.gfp_mask, lru_pages);
 +
mm/vmscan.c:1426:
 +
unsigned long shrink_all_memory(unsigned long nr_pages)
 +
            shrink_slab(sc.nr_scanned, sc.gfp_mask, lru_pages);
 +
mm/vmscan.c:1426:
 +
unsigned long shrink_all_memory(unsigned long nr_pages)
 +
            shrink_slab(nr_pages, sc.gfp_mask, lru_pages);
 +
mm/vmscan.c:1626:
 +
static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
 +
          * shrink_slab() does not currently allow us to determine how
 +
mm/vmscan.c:1626:
 +
static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
 +
          * Note that shrink_slab will free memory on all zones and may
 +
mm/vmscan.c:1626:
 +
static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
 +
        while (shrink_slab(sc.nr_scanned, gfp_mask, order) &&
 +
</div></div>

2015年3月21日 (土) 09:27時点における最新版

TP の素を揃えておこうかと。

C

pthread.c

コマンド引き数で与えられた数だけ、ただ寝てるだけのスレッドを生成するプログラム。

ソースコード

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *thread_func(void *arg) {
    printf("Thread %d\n", (int) arg);
    while (1)
        sleep(1);
}
int main(int argc, char *argv[]) {
    int i, num;
    pthread_t *th;

    if (argc < 2) {
        printf("Usage: %s threads\n", argv[0]);
        return 1;
    }
    if ((num = atoi(argv[1])) < 1) {
        printf("arg 1 = %d\n", num);
        return 1;
    }
    th = (pthread_t *) malloc(sizeof(pthread_t) * num);
    for (i = 0; i < num; i++) {
        pthread_create(&th[i], NULL, &thread_func, (void *) i);
    }
    for (i = 0; i < num; i++) {
        pthread_join(th[i], NULL);
    }
    return 0;
}

実行例

$ cc -l pthread -o pthread pthread.c
$ ./pthread 
Usage: ./pthread threads
$ ./pthread 3 &
[1] 580
Thread 0
Thread 1
Thread 2
$ ps -elfL | grep pthread
0 S hagio      580 13327   580  0    4  77   0 -  8117 -      09:59 pts/5    00:00:00 ./pthread 3
1 S hagio      580 13327   582  0    4  75   0 -  8117 -      09:59 pts/5    00:00:00 ./pthread 3
1 S hagio      580 13327   583  0    4  75   0 -  8117 -      09:59 pts/5    00:00:00 ./pthread 3
1 S hagio      580 13327   584  0    4  75   0 -  8117 -      09:59 pts/5    00:00:00 ./pthread 3
0 S hagio      602 13327   602  0    1  77   0 -  1245 pipe_w 09:59 pts/5    00:00:00 grep pthread
$ kill $!
[1]+  終了しました      ./pthread 3

fork.c

コマンド引き数で与えられた数だけ fork して、ゾンビ状態で放置するプログラム。

ソースコード

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(int argc, char *argv[]) {
    int i, num;
    pid_t pid;

    if (argc < 2) {
        printf("Usage %s procs\n", argv[0]);
        return 0;
    }
    if ((num = atoi(argv[1])) < 0) {
        printf("arg 1 = %d\n", num);
        return 0;
    }
    for (i = 0; i < num; i++) {
        pid = fork();
        if (pid < 0) {
            perror("fork");
            return 1;
        } else if (pid == 0) {
            printf("Child %d\n", i);
            //while (1) sleep(1);
            return 0;
        } else {
            printf("Parent %d (PID: %d)\n", i, pid);
        }
    }
    while (1) sleep(1);
    return 0;
}

実行例

$ cc -o fork fork.c
$ ./fork 3
Child 0
Parent 0 (PID: 1197)
Child 1
Parent 1 (PID: 1198)
Child 2
Parent 2 (PID: 1199)
$ ps -elf | grep fork
0 S hagio     1196 13327  0  75   0 -   378 -      10:30 pts/5    00:00:00 ./fork 3
1 Z hagio     1197  1196  0  76   0 -     0 exit   10:30 pts/5    00:00:00 [fork] <defunct>
1 Z hagio     1198  1196  0  77   0 -     0 exit   10:30 pts/5    00:00:00 [fork] <defunct>
1 Z hagio     1199  1196  0  77   0 -     0 exit   10:30 pts/5    00:00:00 [fork] <defunct>
0 S hagio     1208 31213  0  78   0 -  1245 pipe_w 10:30 pts/4    00:00:00 grep fork

setro.c

ioctl のサンプル。ブロックデバイスの読み込み専用フラグを変更するプログラム。

ソースコード

#include <stdio.h>
#include <fcntl.h>
#include <linux/fs.h>

int main(int argc, char* argv[]) {
    int fd, res, flag;

    if (argc != 3) {
        printf("Usage: %s DEVICE RO_FLAG\n", argv[0]);
        return 1;
    }

    if ((fd = open(argv[1], O_RDWR)) < 0) {
        perror("open");
        return 1;
    }

    flag = atoi(argv[2]);
    if ((res = ioctl(fd, BLKROSET, &flag)) < 0) {
        perror("ioctl");
        close(fd);
        return 1;
    }
    close(fd);
    return 0;
}

実行例

# umount /boot        ★いったんアンマウント
# ./setro /dev/sda1 1 ★リードオンリーにセット
# mount /boot
mount: ブロックデバイス /dev/sda1 は書き込み禁止です、読込み専用でマウントします
# umount /boot
# ./setro /dev/sda1 0 ★リードオンリーを解除
# mount /boot

signal.c

単に受信したシグナル番号を出力するプログラム。

ソースコード

#include <stdio.h>
#include <signal.h>

void signal_handler(int sig) {
    printf("signal: %d\n", sig);
}
int main(void) {
    //signal(SIGINT , SIG_IGN);
    signal(SIGINT , SIG_DFL);
    signal(SIGQUIT, signal_handler);
    signal(SIGALRM, signal_handler);
    signal(SIGTERM, signal_handler);
    alarm(5);
    while (1) {
        sleep(1);
    }
}

実行例

$ ./signal
signal: 3
signal: 3
signal: 15
signal: 14
signal: 3

shm.c

共有メモリの確保と読み書きを行うプログラム。削除は ipcrm で…。

ソースコード

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

#define SHM_SIZE 1024

int main(int argc, char *argv[]) {
    int shmid;
    char *shmaddr;
    char *data;

    if (argc < 2) {
        printf("Usage: %s data [shmid]\n", argv[0]);
        return 1;
    }
    data = argv[1];
    if (argc < 3) {
        if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0666)) < 0) {
            perror("shmget");
            return 1;
        }
        printf("new shmid = %d\n", shmid);
    } else {
        shmid = atoi(argv[2]);
    }

    if ((shmaddr = shmat(shmid, NULL, 0)) < 0) {
        perror("shmat");
        return 1;
    }
    printf("shmaddr = %p\n", shmaddr);
    printf("current value = %s\n", shmaddr);

    strcpy(shmaddr, data);
    printf("written value = %s\n", shmaddr);
}

実行例

$ ./a.out 
Usage: ./a.out data [shmid]
$ ./a.out "test data"
new shmid = 655367
shmaddr = 0xb7fb1000
current value = 
written value = test data
$ ./a.out hoge 655367
shmaddr = 0xb7f27000
current value = test data
written value = hoge
$ ./a.out test 655367
shmaddr = 0xb7fb2000
current value = hoge
written value = test
$ ipcs -m

------ 共有メモリセグメント --------
キー     shmid      所有者  権限     バイト  nattch     状態      
0x00000000 229379     hagio     600        393216     2          対象       
0x00000000 262149     hagio     600        393216     2          対象       
0x00000000 655367     hagio     666        1024       0                       

$ ipcrm -m 655367
$ ipcs -m

------ 共有メモリセグメント --------
キー     shmid      所有者  権限     バイト  nattch     状態      
0x00000000 229379     hagio     600        393216     2          対象       
0x00000000 262149     hagio     600        393216     2          対象       

Python

tcp_server.py / tcp_client.py

簡単な TCP サーバ / クライアントプログラム。例外処理はある程度まで。

tcp_server.py

#!/usr/bin/env python
import sys, socket

port = 55555
if len(sys.argv) > 1:
    try:
        port = int(sys.argv[1])
    except:
        print "Ivalid port number"
        sys.exit(1)

try:
    sock = socket.socket()
    sock.bind(("", port))
    sock.listen(5)
except socket.error, msg:
    print msg
    sys.exit(1)
    
while True:
    print "Waiting for a connection (port: %d)..." % port
    try:
        csock, addr = sock.accept()
        print "Connected by %s:%d" % addr
        while True:
            try:
                buf = csock.recv(1024)
                if not buf:
                    print "Disconnected."
                    break
                print "Received : %s" % buf
            except KeyboardInterrupt:
                break
        csock.close()
    except KeyboardInterrupt:
        break
sock.close()

tcp_client.py

#!/usr/bin/env python
import sys, socket

if len(sys.argv) < 2:
    print "Usage: %s host [port]" % sys.argv[0]
    sys.exit(1)

host = sys.argv[1]
port = 55555
if len(sys.argv) > 2:
    try:
        port = int(sys.argv[2])
    except ValueError:
        print "Invalid port number"
        sys.exit(1)

try:
    sock = socket.socket()
    sock.connect((host, port))
except socket.error, msg:
    print msg
    sys.exit(1)
print "Connected to %s:%d" % (host, port)
while True:
    try:
        buf = raw_input("> ")
        if buf == "q":
            break
        sock.send(buf)
    except KeyboardInterrupt:
        break
sock.close()

実行例

サーバ側:
$ ./tcp_server.py 12345
Waiting for a connection (port: 12345)...
Connected by 127.0.0.1:51522
Received : test data
Disconnected.
Waiting for a connection (port: 12345)...

クライアント側:
$ ./tcp_client.py localhost 12345
Connected to localhost:12345
> test data
> 
> quit

memcurses.py

curses (libcurses) を利用した /proc/meminfo の変化量を表示するスクリプト。

ソースコード

#!/usr/bin/env python
import sys, time, curses

def main(argv):
    win = curses.initscr()
    if len(argv) > 1:
        interval = int(argv[1])
    else:
        interval = 1

    f = open("/proc/meminfo", "r")
    prev = []
    while True:
        win.clear()
        win.addstr(0, 0, "Every %d.0s : %s" % (interval, time.ctime()))
        i = 0
        try:
            for line in f:
                win.addstr(i+2, 0, line[:-1])
                cur = line.split()[1]
                try:
                    if cur != prev[i]:
                        win.addstr(" %+d" % (int(cur) - int(prev[i])))
                        prev[i] = cur
                except IndexError:
                    prev.append(cur)
                i += 1
            win.addstr("\n")
            win.refresh()
            f.seek(0)
            time.sleep(interval)
        except KeyboardInterrupt:
            break

    curses.endwin()
    f.close()
    return 0

if __name__ == "__main__":
    sys.exit(main(sys.argv))

実行例

$ ./memcurses.py 5
Every 5.0s : Sat Feb 26 01:06:31 2011

MemTotal:      5968984 kB
MemFree:        458472 kB
Buffers:        292224 kB +8
Cached:        4135716 kB
SwapCached:          0 kB
Active:        2248520 kB +44
Inactive:      2798728 kB
HighTotal:     5241152 kB
HighFree:       449732 kB
LowTotal:       727832 kB
LowFree:          8740 kB
SwapTotal:     6144852 kB
SwapFree:      6144716 kB
Dirty:             456 kB
Writeback:           0 kB
AnonPages:      619336 kB +32
Mapped:        1179140 kB +112
Slab:           111936 kB -44
PageTables:      12296 kB +52
NFS_Unstable:        0 kB
Bounce:              0 kB
CommitLimit:   9129344 kB
Committed_AS:  1629408 kB
VmallocTotal:   116728 kB
VmallocUsed:     19364 kB
VmallocChunk:    97136 kB
HugePages_Total:     0
HugePages_Free:      0
HugePages_Rsvd:      0
Hugepagesize:     2048 kB

grep.py

grep -Hn と同様の出力となるスクリプト。 標準入力からの入力には非対応。

ソースコード

#!/usr/bin/env python
import sys, re, threading

def grep(reg, path):
    f = open(path, "r")
    row = 1
    for line in f:
        if reg.search(line):
            print "%s:%d:%s" % (path, row, line),
        row += 1
    f.close()

if __name__ == "__main__":
    if len(sys.argv) > 2:
        reg = re.compile(sys.argv[1])
        for path in sys.argv[2:]:
            grep(reg, path)
    else:
        print "Usage: %s PATTERN FILES.." % sys.argv[0]
        sys.exit(1)

実行例

$ ./grep.py
Usage: ./grep.py PATTERN FILES..
$ ./grep.py while *.py
graph.py:9:    while 1:
memcurses.py:13:    while True:
memstat.py:12:    while True:
ncurses.py:8:    while True:
netmonitor.py:32:    while 1:
netstat.py:67:        while True:
netstat.py:132:while True:
open.py:12:while True:
pystat.py:85:while True:
sdx.py:9:    while (q > 0):
tcp_client.py:13:while True:
tcp_server.py:8:while 1:
tcp_server.py:13:        while True:

wc.py

Python で作った wc コマンド。

ソースコード

#!/usr/bin/env python
import sys, getopt

def usage():
    print "Usage: %s [-cmlLw] FILES" % sys.argv[0]

def wc(f):
    (c, m, l, L, w) = (0, 0, 0, 0, 0)
    for line in f:
        c += len(line)
        m += len(line.decode('UTF-8'))
        l += 1
        L  = max(L, len(line)-1)
        w += len(line.split())
    return (c, m, l, L, w)

if __name__ == "__main__":
    try:
        opts, args = getopt.getopt(sys.argv[1:], "cmlLw")
    except getopt.GetoptError:
        usage()
        sys.exit(1)

    # set defaults
    opt_c = True  # bytes
    opt_m = False # chars 
    opt_l = True  # lines
    opt_L = False # max-line-length
    opt_w = True  # words

    if opts:
        (opt_c, opt_l, opt_w) = (False, False, False)
    for (opt, val) in opts:
        if opt == "-c":
            opt_c = True
        elif opt == "-m":
            opt_m = True
        elif opt == "-l":
            opt_l = True
        elif opt == "-L":
            opt_L = True
        elif opt == "-w":
            opt_w = True

    (total_c, total_m, total_l, total_L, total_w) = (0, 0, 0, 0, 0)
    if not args:
        args.append("-")
    for arg in args:
        if arg == "-":
            f = sys.stdin
        else:
            f = open(arg, "r")
        (c, m, l, L, w) = wc(f)
        f.close()
        if opt_l:
            print " %5d" % l,
        if opt_w:
            print " %5d" % w,
        if opt_m:
            print " %5d" % m,
        if opt_c:
            print " %5d" % c,
        if opt_L:
            print " %5d" % L,
        print arg
        total_c += c
        total_m += m
        total_l += l
        total_L = max(total_L, L)
        total_w += w

    if len(args) > 1:
        if opt_l:
            print " %5d" % total_l,
        if opt_w:
            print " %5d" % total_w,
        if opt_m:
            print " %5d" % total_m,
        if opt_c:
            print " %5d" % total_c,
        if opt_L:
            print " %5d" % total_L,
        print "total"

実行例

$ ./wc.py -h
Usage: ./wc.py [-cmlLw] FILES
$ ./wc.py -clmwL *.py | addspace 
    29     80    438    438     45 awk.py
    28     82    719    719     59 buddy.py
    23     70    531    531     65 calc_buddy.py
     4     12     79     79     28 compare.py
    21     55    444    444     43 dec2bin.py
    35     98   1000   1000     49 decode_actlog.py
    87    255   2287   2287     51 graph.py
    20     58    475    475     55 grep.py
    24     78    498    498     43 hex2bin.py
    79    207   1790   1790     71 mail.py
   127    347   3129   3129    109 mail2pens.py
    40     91   1003   1003     71 memcurses.py
    38     77    881    881     63 memstat.py
    21     35    398    398     41 ncurses.py
    54    134   1463   1463    101 netmonitor.py
   144    590   4967   4967    129 netstat.py
    19     30    246    246     40 open.py
    33    105    916    916     57 pygrep.py
   124    376   2977   2977     80 pystat.py
    24     73    510    510     52 sdx.py
    19     43    331    331     40 tcp_client.py
    24     52    523    523     46 tcp_server.py
    84    277   1983   1983     67 wc.py
  1101   3225  27588  27588    129 total
 lines  words  chars  bytes maxlen

calc_buddy.py

/proc/buddyinfo のそれぞれのゾーンの合計サイズを計算するスクリプト。 タイムスタンプを付けて記録したファイルにも対応。

パイプで less などに繋いだ後に Broken Pipe のエラーが出ないように修正。

ソースコード

#!/usr/bin/env python
import sys

if len(sys.argv) == 1:
    files = [ open('/proc/buddyinfo', 'r') ]
    ts_shift = 4;
else:
    files = [ open(f) for f in sys.argv[1:] ]
    ts_shift = 6;

for file in files:
    for line in file:
        try:
            if len(line) > 1:
                print line[:-1],
                fields = line.split()
                total = 0
                for val in range(0,11):
                    total += int(fields[ts_shift + val]) * 4 * 2**val
                print total, "KB"
            else:
                print line,
        except IOError:
            break
    file.close()

実行例

$ ./calc_buddy.py 
Node 0, zone      DMA     46      5      3      0      0      0      0      1      1      1      0  3856 KB
Node 0, zone   Normal    327      2      1      1      1      1      1      0      0      0      1  5916 KB
Node 0, zone  HighMem  78051  15607    279      2     59     17      2      0      0      0      0  448052 KB

dec2bin.py

10 進数を 2 進数に変換するスクリプト。32 ビット限定。

ソースコード

#!/usr/bin/env python
import sys

def dec2bin(dec):
    ret = ""
    for i in range(31, -1, -1):
        if dec & (1 << i):
            ret += "1"
        elif ret:
            ret += "0"
    return ret

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print "Usage: %s dec" % sys.argv[0]
        sys.exit(1)
    try:
        print dec2bin(int(sys.argv[1]))
    except ValueError:
        print "Invalid number"
        sys.exit(1)

実行例

$ ./dec2bin.py
Usage: ./dec2bin.py dec
$ ./dec2bin.py 12345
11000000111001
$ ./dec2bin.py 1024
10000000000
$ ./dec2bin.py -65536
11111111111111110000000000000000
$ ./dec2bin.py 2147483647
1111111111111111111111111111111  // 先頭の 0 は省かれている
$ ./dec2bin.py -2147483648
10000000000000000000000000000000

int2bin.py

上の dec2bin.py を利用して、8, 10, 16 進数に対応させたもの。 コメントアウトしている最後の出力はビット位置確認用。

dec2bin の名前の付け方が悪かったな。

ソースコード

#!/usr/bin/env python
import sys
from dec2bin import dec2bin

def usage():
    print "Usage: %s DEC|'0x'HEX|'0'OCT" % sys.argv[0]
    sys.exit(1)

if __name__ == "__main__":
    if len(sys.argv) < 2:
        usage()
    num = sys.argv[1]
    try:
        if num[:2] == "0x":
            b = dec2bin(int(sys.argv[1], 16))
        elif num[0] == "0":
            b = dec2bin(int(sys.argv[1], 8))
        else:
            b = dec2bin(int(sys.argv[1], 10))
    except ValueError:
        usage()
    l = len(b)
    s = 
    for i in range(0, l, 1):
        r = i % 4
        s = str(2 ** r) + s
    #print s
    print b

実行例

$ ./int2bin.py 
Usage: ./int2bin.py DEC|'0x'HEX|'0'OCT
$ ./int2bin.py 255
11111111
$ ./int2bin.py -255
11111111111111111111111100000001
$ ./int2bin.py 0x12ab
1001010101011
$ ./int2bin.py 0xdeadbeef
11011110101011011011111011101111
$ ./int2bin.py 0755
111101101

bash

cgrep

パターンが呼ばれている関数を検索するスクリプト。 ほとんど awk だけど。

スクリプト

#!/bin/bash
IFS=$'\n'
RESULT=$(grep -nH $@) 
for l in $RESULT; do
    FILE=$(echo "$l" | cut -d: -f 1)
    LINE=$(echo "$l" | cut -d: -f 2)
    gawk -v line=$LINE -v file=$FILE '
        NR < line && /^\w/ && !/:/ {
            cand = $0
            cand_line = NR
        }
        NR == line {
            if ($0 ~ /^\w/) {
                print file ":" line ":"
            } else {
                print file ":" cand_line ":"
                print cand
            }
            gsub("\t", "    ") 
            print $0
            exit
        }
    ' $FILE
done

実行例

$ cgrep -r shrink_slab mm
mm/vmscan.c:177:
unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
mm/vmscan.c:1026:
unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask)
        shrink_slab(sc.nr_scanned, gfp_mask, lru_pages);
mm/vmscan.c:1134:
static unsigned long balance_pgdat(pg_data_t *pgdat, int order)
            nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
mm/vmscan.c:1426:
unsigned long shrink_all_memory(unsigned long nr_pages)
        shrink_slab(nr_pages, sc.gfp_mask, lru_pages);
mm/vmscan.c:1426:
unsigned long shrink_all_memory(unsigned long nr_pages)
            shrink_slab(sc.nr_scanned, sc.gfp_mask, lru_pages);
mm/vmscan.c:1426:
unsigned long shrink_all_memory(unsigned long nr_pages)
            shrink_slab(nr_pages, sc.gfp_mask, lru_pages);
mm/vmscan.c:1626:
static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
         * shrink_slab() does not currently allow us to determine how
mm/vmscan.c:1626:
static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
         * Note that shrink_slab will free memory on all zones and may
mm/vmscan.c:1626:
static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
        while (shrink_slab(sc.nr_scanned, gfp_mask, order) &&