Chinaunix首页 | 论坛 | 博客
  • 博客访问: 158320
  • 博文数量: 42
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 377
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-01 11:18
个人简介

虔诚运维

文章分类

全部博文(42)

文章存档

2014年(42)

我的朋友

分类: LINUX

2014-07-18 15:01:47

      一)概述
   .open系统调用返回的文件描述符是非负整型.
  .每一个进程都有自己的文件描述符集合.
  .当创建进程时,通常有3个打开文件描述符(0,1,2),0代表标准输入,1代表标准输出,2代表标准错误,它们统称为标准IO.
  .当多个描述符指向同一个文件,每个文件描述符仍保持他独特的性能.
  .由于文件描述符在一个进程中是特有的,因此不能在多个进程中间实现共享,而唯一的例外是在父/子进程之间,当一个进程调用fork时,调用fork时打开的所有文件在子进程和父进程中仍然是打开的,而且子进程写入文件描述符会影响到父进程的同一文件描述符,反之亦然.
二)父/子进程对文件描述符的分支使用示例


  源程序如下:
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  void writestr(int fd, char *buf)
  {
  int r = write(fd, buf, strlen(buf));
  if (r == -1)
  perror(buf);
  }
  void busywait(void)
  {
  clock_t t1 = times(NULL);
  while (times(NULL) - t1 < 2);
  }
      int main (int argc, char *argv[])
  {
  int fd = open("thefile.txt",
  O_CREAT | O_TRUNC | O_RDWR,
  S_IRWXU | S_IRWXG | S_IRWXO);
  assert(fd != -1);
  writestr(fd, "This is the parent.\n");
  pid_t pid = fork();
  busywait();
  if(pid == 0){
  writestr(fd,"Child write\n");
  }
  else{
  writestr(fd, "Hi it's me. Im back.\n");
  int status;
  waitpid(pid, &status, 0);
  }
  close(fd);
  return 0;
  }
  编译fork-file.c
  gcc fork-file.c -o fork-file
  执行fork-file,同时查看thefile.txt,如下:
  ./fork-file && cat thefile.txt
  This is the parent.
  Child write
  Hi it's me. Im back.
  ./fork-file && cat thefile.txt
  This is the parent.
  Hi it's me. Im back.
  Child write
  注:
     1)我们发现每次运行结果的顺序都不相同,有时父进程会先调用write系统调用,有时子进程会先调用write.
  2)子进程继承了父进程的文件描述符,如本例子open系统调用得到的文件描述符是3,在子进程和父进程中的文件描述符都是3.
三)文件描述符与/proc
  子目录/proc/self本身就是当前运行进程ID的符号链接.
  用ls -ld查看/proc/self目录的符号链接,发现每次都不一样,说明我们每次用ls命令时的进程ID都是不同的.
  ls -ld /proc/self
  lrwxrwxrwx 1 root root 64 2010-10-10 06:25 /proc/self -> 30525
  我们查看/proc/self/fd目录下的文件描述符,如下:
  ls -l /proc/self/fd
  total 0
  lrwx------ 1 root root 64 2010-10-10 12:16 0 -> /dev/pts/1
  lrwx------ 1 root root 64 2010-10-10 12:16 1 -> /dev/pts/1
  lrwx------ 1 root root 64 2010-10-10 12:16 2 -> /dev/pts/1
  lr-x------ 1 root root 64 2010-10-10 12:16 3 -> /proc/30578/fd
  我们看到了3个标准的IO描述符,它们都被软锭接到了/dev/pts/1,/dev/pts/1是我们通过ssh打开第2个终端,如果是第1个终端,那将是/dev/pts/0.
  如果我们通过ipmi的串口登录,这里应该是/dev/ttySx,而如果是本地登录那应该是/dev/ttyx,如果是单用户登录那将是/dev/console.
  /dev/pts/x是虚拟终端
  /dev/ttySx是串行控制端
  /dev/ttyx是控制台
  /dev/console是单用户控制台
  文件描述符3,这个描述符是ls进程打开/proc/self/fd(也就是/proc/30578/fd)所得到的文件描述符.
  同样我们将ls -l /proc/self/fd的信息输出的一个文件中,如下:
  ls -l /proc/self/fd > /tmp/foo.txt && cat /tmp/foo.txt
  total 0
  lrwx------ 1 root root 64 2010-10-10 12:22 0 -> /dev/pts/1
  l-wx------ 1 root root 64 2010-10-10 12:22 1 -> /tmp/foo.txt
  lrwx------ 1 root root 64 2010-10-10 12:22 2 -> /dev/pts/1
  lr-x------ 1 root root 64 2010-10-10 12:22 3 -> /proc/31005/fd
  这时标准输出的文件描述符不再是/dev/pts/1了,而是/tmp/foo.txt
  再如我们将/dev/null做为标准输入,如下所示:
  ls -l /proc/self/fd > /tmp/foo.txt < /dev/null && cat /tmp/foo.txt
  total 0
  lr-x------ 1 root root 64 2010-10-10 12:30 0 -> /dev/null
  l-wx------ 1 root root 64 2010-10-10 12:30 1 -> /tmp/foo.txt
  lrwx------ 1 root root 64 2010-10-10 12:30 2 -> /dev/pts/1
  lr-x------ 1 root root 64 2010-10-10 12:30 3 -> /proc/31998/fd
      此时标准输入的文件描述符也不再是/dev/pts/1了,而是/dev/null
  最后我们将/dev/null做为标准错误输出,如下所示:
  ls -l /proc/self/fd > /tmp/foo.txt 2< /dev/null && cat /tmp/foo.txt
  total 0
  lrwx------ 1 root root 64 2010-10-10 12:37 0 -> /dev/pts/1
  l-wx------ 1 root root 64 2010-10-10 12:37 1 -> /tmp/foo.txt
  lr-x------ 1 root root 64 2010-10-10 12:37 2 -> /dev/null
  lr-x------ 1 root root 64 2010-10-10 12:37 3 -> /proc/32435/fd
此时标准错误输出的文件描述符也不再是/dev/pts/1了,而是/dev/null


阅读(1012) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~