zoukankan      html  css  js  c++  java
  • linux c学习笔记----进程创建(fork,wait,waitpid)

    1.pid_t fork();

    (1)当一个进程调用了fork 以后,系统会创建一个子进程.这个子进程和父进程不同的地方只有他的进程ID 和父进程ID,其他的都是一样.就象符进程克隆(clone)自己一样.

    (2)为了区分父进程和子进程,我们必须跟踪fork 的返回值. 当fork 掉用失败的时候(内存不足或者是用户的最大进程数已到)fork 返回-1,否则fork 的返回值有重要的作用.对于父进程fork 返回子进程的ID,而对于fork 子进程返回0.我

    们就是根据这个返回值来区分父子进程的.

    (3)一旦子进程被创建,父子进程一起从fork 处继续执行,相互竞争系统的资源.有时候我们希望子进程继续执行,而父进程阻塞直

    到子进程完成任务.这个时候我们可以调用wait 或者waitpid 系统调用.

    vfork(建立一个新的进程)

     
    相关函数
    wait,execve
    表头文件
    #include<unistd.h>
    定义函数
    pid_t vfork(void);
    函数说明
    vfork()会产生一个新的子进程,其子进程会复制父进程的数据与堆栈空间,并继承父进程的用户代码,组代码,环境变量、已打开的文件代码、工作目录和资源限制等。Linux 使用copy-on-write(COW)技术,只有当其中一进程试图修改欲复制的空间时才会做真正的复制动作,由于这些继承的信息是复制而来,并非指相同的内存空间,因此子进程对这些变量的修改和父进程并不会同步。此外,子进程不会继承父进程的文件锁定和未处理的信号。注意,Linux不保证子进程会比父进程先执行或晚执行,因此编写程序时要留意
    死锁或竞争条件的发生。
     
    返回值
    如果vfork()成功则在父进程会返回新建立的子进程代码(PID),而在新建立的子进程中则返回0。如果vfork 失败则直接返回-1,失败原因存于errno中。
    错误代码
    EAGAIN 内存不足。ENOMEM 内存不足,无法配置核心所需的数据结构空间。
    范例
    #include<unistd.h>
    main()
    {
    if(vfork() = =0)
    {
    printf(“This is the child process ”);
    }else{
    printf(“This is the parent process ”);
    }
    }
    执行
    this is the parent process
    this is the child process

    wait(等待子进程中断或结束)
     
    表头文件
    #include<sys/types.h>
    #include<sys/wait.h>
    定义函数
    pid_t wait (int * status);
    函数说明
    wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则
    参数
    status可以设成NULL。子进程的结束状态值请参考waitpid()。
    返回值
    如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno中。

    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中。
     

    例子:#include <unistd.h>

    C代码  收藏代码
      1. <span style="font-size: small;">#include <sys/types.h>  
      2. #include <sys/wait.h>  
      3. #include <stdio.h>  
      4. #include <stdlib.h>  
      5. #include <errno.h>  
      6. #include <math.h>  
      7.   
      8. int main(void) {  
      9.     pid_t child,child2;  
      10.     int status;  
      11.     printf("This will demostrate how to get child status ");  
      12.     if ((child = fork()) == -1) {  
      13.         printf("Fork Error :%s ", strerror(errno));  
      14.         exit(1);  
      15.     } else if (child == 0) {  
      16.         child2 = fork();  
      17.         if(child2 == 0)  
      18.             printf("I am the child2:%ld ",getpid());  
      19.         int i;  
      20.         printf("I am the child:%ld ", getpid());  
      21.         for (i = 0; i < 1000000; i++) sin(i);  
      22.         i = 5;  
      23.         printf("I exit with %d ", i);  
      24.         exit(i);  
      25.     }  
      26.     while (((child = waitpid(getpid(),&status,0)) == -1)&(errno == EINTR));  
      27.     if (child == -1)  
      28.         printf("Wait Error:%s ", strerror(errno));  
      29.     else if (!status)  
      30.         printf("Child %ld terminated normally return status is zero ",  
      31.             child);  
      32.     else if (WIFEXITED(status))  
      33.         printf("Child %ld terminated normally return status is %d ",  
      34.             child, WEXITSTATUS(status));  
      35.     else if (WIFSIGNALED(status));  
      36.     printf("Child %ld terminated due to signal %d znot caught ",  
      37.             child, WTERMSIG(status));  
      38.     getchar();  
      39.     return (EXIT_SUCCESS);  
      40. }  
      41. </span> 
  • 相关阅读:
    @RequestParam 加与不加的区别
    spring boot 实战
    mongo入门
    npm install 错误记录
    AsyncConfigurer 线程池
    guava Preconditions
    mysql分组、合并语句
    maven的学习以及集成开发软件
    Spring MVC+Junit测试出错---@WebAppConfiguration
    mybatis的代码生成器
  • 原文地址:https://www.cnblogs.com/wxb20/p/5921762.html
Copyright © 2011-2022 走看看