加入收藏 | 设为首页 | 会员中心 | 我要投稿 海洋资讯信息网 (https://www.haijunwang.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux下进程控制函数

发布时间:2022-10-28 15:51:33 所属栏目:Linux 来源:
导读:  Linux下进程控制函数

  文章目录

  重要的进程函数 获取进程ID

  #include
  #include
  pid_t getpid(void) //返回调用进程的ID
  pid_t getppid(void) //返回父进程的ID
  创建
  Linux下进程控制函数
 
  文章目录
 
  重要的进程函数 获取进程ID
 
  #include
  #include
  pid_t getpid(void) //返回调用进程的ID
  pid_t getppid(void) //返回父进程的ID
  创建与终止进程 创建进程
 
  #include
  #include
  pid_t fork(void)
  fork出来的进程会获得与父进程用户级虚拟地址空间相同(但是独立)的一份副本,但是PID不同。
 
  fork是一个有趣但令人迷惑的函数,它只被调用一次,但是会返回两次,一次在父进程中,一次在子进程中。在父进程中会返回子进程的pid(非零),在子进程中会返回0,因此可以以此来区分是程序是在子进程中执行还是在父进程中执行。
 
  int main(){
   pid_t pid;
   int x = 1;
   pid = Fork();//fork的包装函数
   if(pid == 0){ /*Child*/
   printf("child : x=%d \n",++x);
   exit(0);
   }
  
   /*Parent*/
   printf("parent:x=%d\n",--x);
   exit(0);
  }
  获得输出:
 
  parent:x=0
  child:x=2
  从结果看出父子进程并不共享数据x,但是共享文件,因为都把输出打到了标志输出stdout上。
 
  终止进程
 
  #include
  void exit(int status);
  回收子进程
 
  僵死进程(zombie process)
 
  终止但未被回收的进程被称为僵尸进程。当一个进程由于某中原因被终止时,内核并不会立刻把它从系统中清除,它会被保持在一种已终止的状态,直到被它的父进程回收。
 
  如果一个僵死进程在被回收之前,父进程就已经结束,那么内核会安排init进程来回收,init进程的pid为1,是所有进程的祖先。
 
  一个进程可以通过调用waitpid函数来等待它的子进程终止:
 
  #include
  #include
  pid_t waitpid(pid_t pid,int *statusp,int options)
  options参数
 
  waitpid中options参数对行为的影响:
 
  options行为
 
  0(默认)
 
  挂起调用线程,若此时pid>0,则等待对应pid的子进程结束,若此时pid=-1,则等待任一子进程结束
 
  WNOHANG
 
  不等待子进程结束,立即返回,若此时返回值为0linux feof函数,表示没有子进程结束
 
  WUNTRACED
 
  挂起调用线程,直到任一子线程终止或者被停止,注意与默认值0的区别为,默认值只返回正常终止的子进程
 
  WCONTINUED
 
  挂起调用线程,直到任一子线程终止,或者任一一个被停止的子线程收到SIGCONT信号重新开始执行
 
  注意options的参数可以进行组合,比如WNOHANG | WUNTRACED。
 
  status参数 status值含义
 
  WIFEXITED(status)
 
  如果子进程通过exit或者return返回,则为真
 
  WEXITSTATUS(status)
 
  返回一个正常终止的子进程的退出状态,只有在WIFEXITED(status)为真时,才会定义这个状态
 
  WIFSIGNALED(status)
 
  如果子进程是因为一个未被捕获的信号终止的,那么就返回真
 
  WTERMSIG(status)
 
  返回导致子进程终止的信号编号,只有当WIFSIGNALED(status)为真时,才定义这个信号
 
  WIFSTOPPED(status)
 
  如果引起返回的子进程当前是停止的,那么久返回真
 
  WSTOPSIG(status)
 
  返回引起子进程停止的信号的编号。只有在WIFSTOPPED()返回为真时,才定义这个状态
 
  WIFCONTINUED(status)
 
  如果子进程收到SIGCONT信号重新启动,则返回真
 
  错误条件
 
  如果调用进程没有子进程,waitpid返回-1,并且设置errorno为ECHILD,
 
  如果waitpid函数被一个信号中断,返回-1,设置errorno为EINTR。
 
  代码演示
 
  #include
  #include
  #include
  #include
  #include
  int main(){
      int status,i;
      const int N = 10;
      pid_t pid;
      for(i = 0; i < N;++i){
          if(fork() == 0){
              printf("It's child \n");
              exit(100+i);
          }
      }
      while((pid = waitpid(-1,&status,0)) > 0){
          if(WIFEXITED(status))
              printf("child %d terminate normally with exit status = %d\n",
                      pid,WEXITSTATUS(status));
          else
              printf("child %d termintate abnormally \n");
      }
      exit(0);
  }
  注意子进程退出的顺序不是一定的,如果要让父进程按照子进程创建的顺序来回收子进程,可以做出如下修改:
 
  #include
  #include
  #include
  #include
  #include
  int main(){
      int status,i;
      const int N = 10;
      pid_t pid[N],retpid;
      for(i = 0; i < N;++i){
          if(fork() == 0){
              exit(100+i);
          }
      }
   i = 0;
      while((retpid= waitpid(pid[i++],&status,0)) > 0){
          if(WIFEXITED(status))
              printf("child %d terminate normally with exit status = %d\n",
                      pid,WEXITSTATUS(status));
          else
              printf("child %d termintate abnormally \n");
      }
      exit(0);
  }
  wait函数
 
  wait函数时waitpid的简单版本:
 
  #include
  #include
  pid_t wait(int *startup)
  调用wait函数等价于调用waitpid(-1,&status,0)。
 
  让进程休眠 sleep函数
 
  sleep函数会让进程挂起一段时间:
 
  #include
  unsigned int sleep(unsigned int secs);
  如果挂起时间到,函数返回0,如果被中断而导致返回,将返回剩余的挂起时间。
 
  pause函数
 
  pause函数会将进程挂起,直到进程收到一个信号
 
  #include
  int pause(void)
  加载并运行新的程序
 
  execve函数可以在当前进程的上下文中加载并允许一个新的程序
 
  #include
  int execve(const char* filename,const char* argv[],
  const char* envp[]);
  其中argv与envp均指向以Null为结尾的指针数组;
 
  在使用中,可以用environ(系统全局变量)变量传入envp[]数组中。
 
  环境变量相关函数
 
  获取环境变量
 
  #include
  char* getenv(const char* name);
  设置与取消环境变量
 
  #include
  int setenv(const char* name,const char* newvalue,int overwrite);
  void unsetenv(const char* name);
  一般来说,环境变量已"name=value"这样键值对的方式存在。
 
  利用进程控制接口,编写简单的shell程序
 
  #include
  #include
  #include
  #include
  #include
  #define MAX_COMMAND_LINE 256
  #define MAX_COMMAND_COUNT 256
  void eval(char* command);
  int parseline(char* command,char* argv[]);
  int builtin_command(char* argv[]);
  int main(){
      char commandline[MAX_COMMAND_LINE];
      while (1){
          printf("> ");
          fgets(commandline,MAX_COMMAND_LINE,stdin);
          if(feof(stdin)){
              exit(0);
          }
          eval(commandline);
      }
      
      exit(0);
  }
  void eval(char* command){
      int argc = 0;
      char* argv[MAX_COMMAND_COUNT];
      pid_t pid;
      int status;
      int bg = parseline(command,argv);
      if(argv[0] == NULL){
          return ;
      }
      if(builtin_command(argv)){
          return ;
      }
      if((pid = fork()) == 0){
          printf("execute child \n");
          if(execve(argv[0],argv,__environ)<0){
              printf("Can't find command %s \n",argv[0]);
              exit(0);
          }
      }
      if(!bg){
          if(waitpid(pid,&status,0) < 0){
              printf("Fail to excute pid %d command %s \n",pid,argv[0]);
          }
          if(WIFSTOPPED(status)){
              printf("the stoped signal is %d \n",WSTOPSIG(status));
          }
      } else{
          // waitpid(-1,&status,WNOHANG);
          printf("pid:%d command:%s run in background \n",pid,argv[0]);
      }
  }
  int parseline(char* command,char* argv[]){
      int argc = 0;
      char* delim;
      command[strlen(command)-1]=' ';
      while(*command && command[0] == ' '){
          ++command;
      }
      while((delim = strchr(command,' '))){
          *delim='\0';
          argv[argc++] = command;
          command = (++delim);
          while (*command &&command[0] == ' '){
              ++command;
          }
      }
      argv[argc] = NULL;
      if(argc == 0){
          return 0;
      }
      if(*argv[argc-1] == '&'){
          argv[--argc] = NULL;
          return 1;
      } else{
          return 0;
      }
  }
  int builtin_command(char* argv[]){
      if(!strcmp(argv[0],"quit")){
          exit(0);
      } else if(!strcmp(argv[0],"&")){
          return 1;
      }
      return 0;
  }
 

(编辑:海洋资讯信息网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!