LoginSignup
5
6

More than 5 years have passed since last update.

Linux プロセス間通信について pipe()を読む

Last updated at Posted at 2016-04-10

今回はsys_pipe()を読む
カーネルのバージョンはlinux-4.5

UNIXで利用できるプロセス間通信の仕組み

UNIXで使用されているプロセス間通信のざっくり分類

  • パイプとFIFO ←今回はココについて書くよ!
  • セマフォ
  • IPC(systemV)
    • メッセージ
    • 共有メモリリージョン
  • ソケット
    • 19章では、ほぼ解説なし?

パイプ処理にあたり重要な関数

  • pipe() ←とりまコレを読む
    • popen() ←pipe()を使用してる
    • pclose()
  • fork()
  • close()
  • dup2()
  • execve()
  • dup3()

POSIXでは片方向のパイプしか定義していない
→双方向通信が必要な場合はpipe()を2回行う

pipe()を読む

pipe()のシステムコールを見つけたくてsys_pipeでgrepしたらこんなコードが見つかった

fs/pipe.c
SYSCALL_DEFINE1(pipe, int __user *, fildes)
{
        return sys_pipe2(fildes, 0);
}

sys_pipe2は arch/x86/entry/syscalls/syscall_32.tbl
331 i386 pipe2 sys_pipe2
にこんな感じで書かれてる

で?どこにsys_pipe2があんの?
gtagsで定義元にジャンプしようとしても"sys_pipe2: tag not found"と言われてしまった
linux-2.6.0ばっかりよんでたのでsys_pipe2でgrepして見つからないと途方にくれてしまう、、、、

実はSYSCALL_DEFINE1(pipe, int __user *, fildes)の真上にこんな関数がある
これがsys_pipe2の正体っぽい

fs/pipe.c
SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags)
{
        struct file *files[2];
        int fd[2];
        int error;

        error = __do_pipe_flags(fd, files, flags);
        if (!error) {
                if (unlikely(copy_to_user(fildes, fd, sizeof(fd)))) {
                        fput(files[0]);
                        fput(files[1]);
                        put_unused_fd(fd[0]);
                        put_unused_fd(fd[1]);
                        error = -EFAULT;
                } else {
                        fd_install(fd[0], files[0]);
                        fd_install(fd[1], files[1]);
                }
        }
        return error;
}

どうやら2.6とは違いsys_*でシステムコールを定義しなくなったらしい
で、このSYSCALL_DEFINEが何なのかについては素晴らしいサイトがあったのでそちらを見てください(丸投げ)

SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags)を例にザックリ説明すると

属性 意味
SYSCALL_DEFINE2 2はシステムコールの引数の数 1,3もあるよ
pipe2 システムコール名 sys_システムコール名を定義する
int __user * ???
fildes 引数1
int, flags SYSCALL_DEFINEでは型名と引数名を,で区切る

こんな感じ

sys_pipe2のザックリ概要のコメントを書いたのがコチラ

fs/pipe.c
SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags)
{
        struct file *files[2];
        int fd[2];
        int error;

        //flagsを見てerrorかどうか判定とかしてる
        error = __do_pipe_flags(fd, files, flags);
        if (!error) {
                if (unlikely(copy_to_user(fildes, fd, sizeof(fd)))) {
                        fput(files[0]);
                        fput(files[1]);
                        put_unused_fd(fd[0]);
                        put_unused_fd(fd[1]);
                        error = -EFAULT;
                } else {
                        fd_install(fd[0], files[0]);
                        fd_install(fd[1], files[1]);
                }
        }
        return error;
}

このlinuxのsys_pipeですが、xv6のpipe()とっても近い

int p[2];
char *argv[2];

argv[0] = "wc";
argv[1] = 0;

pipe(p);
if(fork() == 0) {
  close(0);
  dup(p[0]);
  close(p[0]);
  close(p[1]);
  exec("/bin/wc", argv);
} else {
  write(p[1], "hello world\n", 12);
  close(p[0]);
  close(p[1]);
}
5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6