サンプルプログラム集
TP の素を揃えておこうかと。
目次
C
pthread.c
コマンド引き数で与えられた数だけ、ただ寝てるだけのスレッドを生成するプログラム。
ソースコード <toggledisplay>
#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; }
</toggledisplay>
実行例 <toggledisplay>
$ 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
</toggledisplay>
fork.c
コマンド引き数で与えられた数だけ fork して、ゾンビ状態で放置するプログラム。
ソースコード <toggledisplay>
#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; }
</toggledisplay>
実行例 <toggledisplay>
$ 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
</toggledisplay>
Python
tcp_server.py / tcp_client.py
簡単な TCP サーバ / クライアントプログラム。例外処理はある程度まで。
tcp_server.py <toggledisplay>
#!/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()
</toggledisplay>
tcp_client.py <toggledisplay>
#!/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()
</toggledisplay>
実行例 <toggledisplay>
サーバ側: $ ./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
</toggledisplay>
memcurses.py
curses (libcurses) を利用した /proc/meminfo の変化量を表示するスクリプト。
ソースコード <toggledisplay>
#!/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))
</toggledisplay>
実行例 <toggledisplay>
$ ./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
</toggledisplay>
grep.py
grep -Hn
と同様の出力となるスクリプト。
標準入力からの入力には非対応。
ソースコード <toggledisplay>
#!/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)
</toggledisplay>
実行例 <toggledisplay>
$ ./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:
</toggledisplay>
wc.py
Python で作った wc コマンド。
ソースコード <toggledisplay>
#!/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"
</toggledisplay>
実行例 <toggledisplay>
$ ./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
</toggledisplay>
calc_buddy.py
/proc/buddyinfo のそれぞれのゾーンの合計サイズを計算するスクリプト。 タイムスタンプを付けて記録したファイルにも対応。
パイプで less などに繋いだ後に Broken Pipe のエラーが出ないように修正。
ソースコード <toggledisplay>
#!/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() </toggledisplay>
実行例 <toggledisplay>
$ ./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
</toggledisplay>
dec2bin.py
10 進数を 2 進数に変換するスクリプト。32 ビット限定。
ソースコード <toggledisplay>
#!/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)
</toggledisplay>
実行例 <toggledisplay>
$ ./dec2bin.py 12345 11000000111001 $ ./dec2bin.py 1024 10000000000 $ ./dec2bin.py -65536 11111111111111110000000000000000 $ ./dec2bin.py 2147483647 1111111111111111111111111111111 $ ./dec2bin.py -2147483648 10000000000000000000000000000000
</toggledisplay>
bash
cgrep
パターンが呼ばれている関数を検索するスクリプト。 ほとんど awk だけど。
スクリプト <toggledisplay>
#!/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
</toggledisplay>
実行例 <toggledisplay>
$ 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) &&
</toggledisplay>