Unix/Linuxプログラミング理論と実践 8章 (sh)

shをつくる

p.341

char *cp, *malloc();

これはi686-apple-darwin9-gcc-4.0.1だとエラーが出る

psh1.c:43: error: conflicting types for ‘malloc’

なので以下のように修正

char *cp;
extern void *malloc();

ProductName Unix/Linuxプログラミング理論と実践
Bruce Molay
アスキー・メディアワークス / ¥ 6,090 ()
在庫あり。

Unix/Linuxプログラミング理論と実践 8章 (execvp)

別のプログラムを起動するプログラム

#include <stdio.h>

int main()
{
  char *arglist[3];
  arglist[0] = "ls";
  arglist[1] = "-l";
  arglist[2] = 0;

  printf("* * * About to exec ls -l\n");
  execvp( "ls" , arglist );
  printf("* * * ls is done. bye\n");
}

arglist[2]に0が入ってるのがわからん。arglist[0]はプログラム名であり変更できる。

#include <stdio.h>

int main()
{
  char *arglist[2];
  arglist[0] = "sleeeeeeeeeeeP!";
  arglist[1] = "10";

  printf("* * * About to exec ls -l\n");
  execvp( "sleep" , arglist );
  printf("* * * ls is done. bye\n");
}

これを実行してpsで見てみると

$ ps
  PID TTY           TIME CMD
  149 ttys000    0:00.06 -bash
86661 ttys002    0:00.21 -bash
87689 ttys002    0:00.01 sleeeeeeeeeeeP! 10

コマンド名は実行した側が任意につけられるのか。

ProductName Unix/Linuxプログラミング理論と実践
Bruce Molay
アスキー・メディアワークス / ¥ 6,090 ()
在庫あり。

Unix/Linuxプログラミング理論と実践 7章 (イベント駆動プログラミング)

引き続きcursesライブラリを使って。7章は理解しながら読むのにちょっと時間がかかった。

ProductName Unix/Linuxプログラミング理論と実践
Bruce Molay
アスキー・メディアワークス / ¥ 6,090 ()
在庫あり。

Unixでは非同期入力のためにO_ASYNCを使う方法とaio_readを使う二種類があるらしい。前者は入力が読み出せるようになったときにシグナルを送り、後者は入力を読んだあとにシグナルを送るらしい。

Unix/Linuxプログラミング理論と実践 7章 (シグナル)

シグナル

ProductName Unix/Linuxプログラミング理論と実践
Bruce Molay
アスキー・メディアワークス / ¥ 6,090 ()
在庫あり。

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

#define INPUTLEN 100

int main(int ac, char *av[])
{
  void inthandler(int);
  void quithandler(int);
  char input[INPUTLEN];
  int nchars;

  signal( SIGINT, inthandler );
  signal( SIGQUIT, quithandler );

  do {
    printf("\nType a message\n");
    nchars = read(0, input, (INPUTLEN-1));
    if ( nchars == -1 )
      perror("read returned an error");
    else {
      input[nchars] = '\0';
      printf("You typed: %s", input);
    }
  }
  while( strncmp( input , "quit" , 4 ) != 0 );
}

void inthandler(int s) 
{
  printf(" Received signal %d .. waiting\n", s );
  sleep(2);
  printf(" Leaving inthandler \n");
}

void quithandler(int s)
{
  printf(" Received signal %d .. waiting\n", s);
  sleep(3);
  printf(" Leaving quithandler \n");
}

実行してみる

Type a message
^C Received signal 2 .. waiting
^C^C^C Leaving inthandler 
 Received signal 2 .. waiting
 Leaving inthandler 

macbookでやってみると二番目のシグナルはブロックされて、三番目以降のシグナルは無視される。

Unix/Linuxプログラミング理論と実践 7章 (インターバルタイマ)

interval timerを使うと定期的にシグナルを送れる。

ProductName Unix/Linuxプログラミング理論と実践
Bruce Molay
アスキー・メディアワークス / ¥ 6,090 ()
在庫あり。

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>

int main()
{
  void countdown(int);

  signal(SIGALRM, countdown);
  if ( set_ticker(50) == -1)
    perror("set_ticker");
  else
    while( 1 )
      pause();
  return 0;
}

void countdown(int signum)
{
  static int num = 10;
  printf("%d ..", num--);
  fflush(stdout);
  if ( num < 0 ){
    printf("DONE!\n");
    exit(0);
  }
}

int set_ticker( int n_msecs )
{
  struct itimerval new_timeset;
  long n_sec, n_usecs;

  n_sec = n_msecs / 1000;
  n_usecs = ( n_msecs % 1000 ) * 1000L;

  new_timeset.it_interval.tv_sec = n_sec;
  new_timeset.it_interval.tv_usec = n_usecs;

  new_timeset.it_value.tv_sec = n_sec;
  new_timeset.it_value.tv_usec = n_usecs;

  return setitimer(ITIMER_REAL, &new_timeset, NULL);
}

sleepは秒単位だけどusleep使えばmicrosecondで一時停止できる

Unix/Linuxプログラミング理論と実践 6章 (端末制御)

端末に関して、カノニカルモードとかノンブロッキングとか。あとシグナル処理。

ProductName Unix/Linuxプログラミング理論と実践
Bruce Molay
アスキー・メディアワークス / ¥ 6,090 ()
在庫あり。

端末を非カノニカル(cr)モードにするには

  • ICANONビットをオフにする
  • 制御文字バッファのVMIN要素に1をセット

ノンブロッキングモードにするには

  • O_NDELAYビットをONにする

Unix/Linuxプログラミング理論と実践 5章 (stty)

端末ドライバのプログラミング。

writeなんてコマンドがあるのか。

ProductName Unix/Linuxプログラミング理論と実践
Bruce Molay
アスキー・メディアワークス / ¥ 6,090 ()
在庫あり。

  • flagset |= MASK (bitをセット)
  • flagset &= ~MASK (bitをクリア)

ioctlシステムコールにはほとんど触れてない。

Unix/Linuxプログラミング理論と実践 4章 (pwdを書く)

pwdコマンドはinodeを親ディレクトリに辿っていく。ルートディレクトリは. と..が同じinodeを指す。

macbookでls -ia。

$ ls -ia /
      2 ./                                               31452 Users/
      2 ../                                              22730 Volumes/

ので.と..のinodeをチェックしながら再帰的に辿るという実装。

void printpathto( ino_t this_inode )
{
  ino_t my_inode;
  char  its_name[BUFSIZ];

  if ( get_inode( ".." ) != this_inode )
    {
      chdir( ".." );

      inum_to_name(this_inode, its_name, BUFSIZ);

      my_inode = get_inode( "." );
      printpathto( my_inode );
      printf("/%s",its_name );
    }
}

ProductName Unix/Linuxプログラミング理論と実践
Bruce Molay
アスキー・メディアワークス / ¥ 6,090 ()
在庫あり。

ダブル間接ブロックとトリプル間接ブロック

Unix/Linuxプログラミング理論と実践 3章 (lsを書く)

lsを書く。

ProductName Unix/Linuxプログラミング理論と実践
Bruce Molay
アスキー・メディアワークス / ¥ 6,090 ()
在庫あり。

ファイルタイプとパーミッションを調べるのにマスキングを使う。

sys/stat.hのファイルタイプのとこ

/* File type */
#define S_IFMT          0170000         /* [XSI] type of file mask */
#define S_IFIFO         0010000         /* [XSI] named pipe (fifo) */
#define S_IFCHR         0020000         /* [XSI] character special */
#define S_IFDIR         0040000         /* [XSI] directory */
#define S_IFBLK         0060000         /* [XSI] block special */
#define S_IFREG         0100000         /* [XSI] regular */
#define S_IFLNK         0120000         /* [XSI] symbolic link */
#define S_IFSOCK        0140000         /* [XSI] socket */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define S_IFWHT         0160000         /* whiteout */
#define S_IFXATTR       0200000         /* extended attribute */
#endif

man ls

b     Block special file.
c     Character special file.
d     Directory.
l     Symbolic link.
s     Socket link.
p     FIFO.
-     Regular file.

Unix/Linuxプログラミング理論と実践 2章(cpを書く)

システムコールを使ってcpコマンドを書く。

ProductName Unix/Linuxプログラミング理論と実践
Bruce Molay
アスキー・メディアワークス / ¥ 6,090 ()
在庫あり。

そのあと、バッファするバージョンのwhoコマンドを書く。