• Linux环境编程--waitpid与fork与execlp


    waitpid

      waitpid(等待子进程中断或结束)
      表头文件
      #include<sys/types.h>
      #include<sys/wait.h>
      定义函数 pid_t waitpid(pid_t pid,int * status,int options);
      函数说明
      waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程
      结束。如果在调用 wait()时子进程已经结束,则 wait()会立即
      返回子进程结束状态值。 子进程的结束状态值会由参数 status 返回,
      而子进程的进程识别码也会一起返回。如果不在意结束状态值,则
      参数 status 可以设成 NULL。参数 pid 为欲等待的子进程识别码,
      其他数值意义如下:
      pid<-1 等待进程组识别码为 pid 绝对值的任何子进程。
      pid=-1 等待任何子进程,相当于 wait()。 
      pid=0 等待进程组识别码与目前进程相同的任何子进程。 
      pid>0 等待任何子进程识别码为 pid 的子进程。
      参数 option 可以为 0 或下面的 OR 组合:
      WNOHANG 如果没有任何已经结束的子进程则马上返回, 不予以等待。
      WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
      子进程的结束状态返回后存于 status,底下有几个宏可判别结束情况:
      WIFEXITED(status)如果子进程正常结束则为非 0 值。
      WEXITSTATUS(status)取得子进程 exit()返回的结束代码,一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏。
      WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真
      WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED 来判断后才使用此宏。
      WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为真。一般只有使用 WUNTRACED 时才会有此情况。
      WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用 WIFSTOPPED 来判断后才使用此宏。
      如果执行成功则返回子进程识别码(PID) ,如果有错误发生则返回
      返回值-1。失败原因存于 errno 中。
     
     
     /******
      * waitpid.c - Simple wait usage
      *********/
       #include <unistd.h>
      #include <sys/types.h>
      #include <sys/wait.h>
      #include <stdio.h>
      #include <stdlib.h>
      int main( void )
      {
      pid_t childpid;
      int status;
      childpid = fork();
      if ( -1 == childpid )
      {
      perror( "fork()" );
      exit( EXIT_FAILURE );
      }
      else if ( 0 == childpid )
      {
      puts( "In child process" );
      sleep( 3 );//让子进程睡眠3秒,看看父进程的行为
      printf("	child pid = %d
    ", getpid());
      printf("	child ppid = %d
    ", getppid());
      exit(EXIT_SUCCESS);
      }
      else 
      {
      waitpid( childpid, &status, 0 );
      puts( "in parent" );
      printf( "	parent pid = %d
    ", getpid() );
      printf( "	parent ppid = %d
    ", getppid() );
      printf( "	child process exited with status %d 
    ", status );
      }
      exit(EXIT_SUCCESS);
      }

      [root@localhost src]# gcc waitpid.c 
      [root@localhost src]# ./a.out 
      In child process
      child pid = 4469
      child ppid = 4468
      in parent
      parent pid = 4468
      parent ppid = 4379
      child process exited with status 0 
      [root@localhost src]# 
      如果将上面“waitpid( childpid, &status, 0 );”行注释掉,程序执行效果如下:
      [root@localhost src]# ./a.out 
      In child process
      in parent
      parent pid = 4481
      parent ppid = 4379
      child process exited with status 1331234400 
      [root@localhost src]# child pid = 4482
      child ppid = 1
      子进程还没有退出,父进程已经退出了。

    fork

      fork函数创建子进程,子进程获得父进程数据空间、堆、栈等资源的副本。克隆父进程的代码,克隆代码的执行位置
            注意父子进程是同时执行的
          
       1.父进程先退出,子进程就依托根进程init:孤儿进程。
        孤儿进程没有任何危害
           2.子进程先退出
              子进程会成为僵尸进程。僵尸进程不会占用内存,cpu
       僵尸进程造成进程名额资源浪费
           3.僵尸进程使用wait回收
           4.父进程怎么知道进程退出?
              子进程结束通常会向父进程发送一个信号SIGCHLD或17
            5.父进程处理子进程退出信号
               signal(int sig,void(*)(int));
              系统注册,只要sig信号发生,系统停止进程
               当函数执行完毕,继续原来进程
               5.1 实现处理函数
               5.2使用signal绑定信号函数
             6.父子进程的资源访问
                6.1内存资源
        映射内存:
                                 mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS |MAP_SHARED,0, 0);
                               MAP_SHARED:映射到同一物理内存
                                 MAP_PRIVATE:映射到不同物理内存
                 6.2文件资源
             两个进程之间,文件描述符号指向的时候同一个文件内核数据结构
              7.多进程与文件锁(建议锁)
     
       
     
           fork()函数,Linux系统调用
      头文件:
      #include <unistd.h>
      函数定义:
      int fork( void );
      返回值:
       子进程中返回0,子进程不调用fork()所以是0
           父进程中返回子进程ID,
           出错返回-1
      函数说明:
      一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。
      子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。
          注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间,它们之间共享的存储空间只有代码段。
      示例代码:
      
       #include <unistd.h>
      #include <stdio.h>
      int main(int argc, void ** argv )
      {
      int pid = fork();
      if(pid < 0 ) {
      // print("error!");
      } else if( pid == 0 ) {
      // print("This is the child process!");
      } else {
      // print("This is the parent process! child process id = %d", pid);
      }
      return 0;
      }

    execlp

      execlp(从PATH 环境变量中查找文件并执行)
     
          1.execl不会创建新的进程
        2.execl替换当前进程的代码。如果替换成功,execl之后的代码,将不会执行
          3.execl和execlp的区别
              execl指当前路径,必须要写出指令的相对路径或者绝对路径
              execlp使用系统的搜索路径(which能找到的指令都能执行)
           
      相关函数:
      fork,execl,execle,execv,execve,execvp
      表头文件:
      #include<unistd.h>
      定义函数:
      int execlp(const char * file,const char * arg,……)
       第一个参数 文件的路径
             第二参数  指令的名字
              .....      指令的参数
      函数说明:
      execlp()会从PATH 环境变量所指的目录中查找符合参数file的文件名,找到后便执行该文件,
          然后将第二个以后的参数当做该文件的argv[0]、argv[1]……,
         最后一个参数必须用空指针(NULL)作结束。
      返回值:
      如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中。
      错误代码 参考execve()。
      范例:
      
       /* 执行ls -al /etc/passwd execlp()会依PATH 变量中的/bin找到/bin/ls */
      #include<unistd.h>
      main()
      {
      execlp(“ls”,”ls”,”-al”,”/etc/passwd”,(char *)0);
      }

      执行:
      -rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
      ————————————————————————————————add by love_aiqiu
      NAME
      execl, execlp, execle, execv, execvp - execute a file
      SYNOPSIS
      #include <unistd.h>
      extern char **environ;
      int execl(const char *path, const char *arg, ...);
      int execlp(const char *file, const char *arg, ...);
      int execle(const char *path, const char *arg , ..., char * const envp[]);
      int execv(const char *path, char *const argv[]);
      int execvp(const char *file, char *const argv[]);
  • 相关阅读:
    《Windows核心编程系列》十四谈谈默认堆和自定义堆
    《windows核心编程系列》十五谈谈windows线程栈
    《Windows核心编程系列》十三谈谈在应用程序中使用虚拟内存
    《Windows核心编程系列》十二谈谈Windows内存体系结构
    《Windows核心编程系列》十一谈谈Windows线程池
    Extjs利用vtype验证表单
    Extjs文本输入框
    Extjs文本输入域
    远程数据源Combobox
    Extjs整体加载树节点
  • 原文地址:https://www.cnblogs.com/mingfeng002/p/6905007.html
Copyright © 2020-2023  润新知