APUE–fork()函数介绍



一、fork()系统调用介绍

1.fork()创建子进程特点

fork()用于创建子进程,一次调用会有两个返回(return),一次返回给父进程子进程的PID(Process ID),一次返回给子进程,其返回值为0.

  • 返回值=0,子进程在运行
  • 返回值>0,父进程在运行
  • 返回值<0,fork()调用出错

进程获取自己的PID:getpid()
进程获取父进程PID:getppid()
由于一个进程可创建多个子进程,没有函数可以获取其子进程PID

2. 子进程的特点

创建新的子进程成功后,将父进程的文本段、数据段、堆栈都复制一份给子进程,但子进程有自己独立的空间,子进程对这些内存的修改并不会影响父进程空间的相应内存

父、子进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。若要确保让父进程或子进程先执行,则需要程序员在代码中通过进程间通信的机制来实现

子进程继承的东西

  • 进程的资格、用户号(UIDS)和组号(GIDS)
  • 环境变量
  • 内存
  • 打开的文件描述符
  • 执行时关闭标志
  • 信号控制设定
  • nice值(由nice函数设定,进程的优先级,数值小的优先级高)
  • 进程调度类别
  • 进程组号
  • 对话期ID
  • 当前工作目录
  • 根目录
  • 文件方式创建屏蔽字
  • 资源控制
  • 控制终端

子进程独有

  • 进程号
  • 不同的父进程号
  • 自己的文件描述符、目录流的拷贝
  • 资源使用设定为0
  • 不继承父进程的进程、正文、数据和其他锁定内存
  • tms结构中的系统时间
  • 阻塞信号集初始化为空集
  • time_create函数创建的计时器
  • 异步输入和输出
  • 父进程设置的锁

二、代码示例

1.fork()创建子线程

  #include<stdio.h>
  #include<unistd.h>
  #include<string.h>
  #include<errno.h>
   
  int main(int argc, char **argv)
  {
       pid_t       pid;
   
      printf("Parent process PID[%d] start running...\n",getpid() );
  
      pid = fork();	//创建子进程
      if( pid < 0 )	//fork()错误
      {
          printf("fock() create child process failure:%s\n",strerror(errno));
          return -1;
      }
      else if( 0 == pid )		//子进程正在运行
      {
          printf("Child process PID[%d] start running,my parent PID is [%d]\n",          getpid(),getppid());
          return 0;
      }
      else if( pid >0 )	//父进程正在运行
      {
          printf("Parent process PID[%d] continue running,and child process PID is       [%d]\n",getpid(),pid);
          return 0;
      }
  }

2.子进程对内存修改

  #include<stdio.h>
  #include<unistd.h>
  #include<string.h>
  #include<errno.h>
  
  int g_var = 7;
  char g_buf[]="A string write to stdout.\n";
  int main(int argc, char ** argv)
  {
      int     var = 85;
      pid_t   pid;
  
      if( write(STDOUT_FILENO,g_buf,sizeof(g_buf)-1) < 0 )	//将g_buf[]中的内容输出到屏幕上,除\n(换行)外,
      {
          printf("write string to stdout error:%s\n",strerror(errno));
          return -1;
      }
  
      printf("Before fork\n");
  
      if( (pid=fork()) < 0 )		//fork出错
      {
          printf("fork() error:%s\n",strerror(errno));
          return -2;
      }
      else if( 0 == pid )		//子进程正在运行
      {
          printf("Child process PID[%d] running...\n",getpid());
          g_var ++;
          var ++;
      }
      else		//父进程正在运行
      {
          printf("Parent process PID[%d] waiting...\n",getpid());
          sleep(1);	//让子进程先运行
      }
  
      printf("PID=%ld,g_var=%d,var=%d\n",(long)getpid(),g_var,var);
      return 0;
  }

程序执行结果如下:

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐