zoukankan      html  css  js  c++  java
  • fork()

    fork系统调用

    #include <unistd.h>
    #include <stdio.h>
    
    int main()
    {
        pid_t pid;
        int count =0;
        pid = fork();
        if(pid < 0)
        {
            printf("error!");
        }
        else if(pid == 0)
        {
            printf("i am child %d 
    ",getpid());
            count++;
        }
        else
        {
            printf("i am father %d
    ",getpid());
            count++;
        }
      //两次输出的都是1 printf(
    "count:%d ",count); return 0; }

    fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
        1)在父进程中,fork返回新创建子进程的进程ID;
        2)在子进程中,fork返回0;
        3)如果出现错误,fork返回一个负值;

     fork出错可能有两种原因:
        1)当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN。
        2)系统内存不足,这时errno的值被设置为ENOMEM。

    fork把进程当前的情况拷贝一份,不是从代码开始处拷贝的。一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。

    #include <unistd.h>
    #include <stdio.h>
    
    int main()
    {
        int i = 0;
        for(i = 0;i < 2;++i)
        {
            pid_t pid = fork();
            if(pid == 0)
            {
                printf("i = %d child %d %d
    ",i,getpid(),getppid());
            }
            else
            {
                printf("i = %d father %d childid = %d %d
    ",i,getpid(),pid,getppid());
            }
        }
        return 0;
    }

    输出:

    i = 0 father 3020 childid = 3021 2650
    i = 1 father 3020 childid = 3022 2650
    i = 1 child 3022 1662
    i = 0 child 3021 1662
    i = 1 father 3021 childid = 3023 1662
    i = 1 child 3023 1662

    注意,上述进程如果跑完循环,就死亡了,这样子进程就没有父进程了,这在操作系统中是不被允许的 ,所以置为1662

    对于这种N次循环的情况,执行printf函数的次数为2*(1+2+4+……+2N-1)次,创建的子进程数为1+2+4+……+2N-1

    #include <unistd.h>
    #include <stdio.h>
    int main() {
        pid_t fpid;//fpid表示fork函数返回的值
        //printf("fork!");
        printf("fork!/n");
        fpid = fork();
        if (fpid < 0)
            printf("error in fork!");
        else if (fpid == 0)
            printf("I am the child process, my process id is %d/n", getpid());
        else
            printf("I am the parent process, my process id is %d/n", getpid());
        return 0;
    }

        执行结果如下:
        fork!
        I am the parent process, my process id is 3361
        I am the child process, my process id is 3362 
        如果把语句printf("fork!/n");注释掉,执行printf("fork!");
        则新的程序的执行结果是:
        fork!I am the parent process, my process id is 3298
        fork!I am the child process, my process id is 3299 
        程序的唯一的区别就在于一个/n回车符号,为什么结果会相差这么大呢?
        这就跟printf的缓冲机制有关了,printf某些内容时,操作系统仅仅是把该内容放到了stdout的缓冲队列里了,并没有实际的写到屏幕上。但是,只要看到有/n 则会立即刷新stdout,因此就马上能够打印了。
        运行了printf("fork!")后,“fork!”仅仅被放到了缓冲里,程序运行到fork时缓冲里面的“fork!”  被子进程复制过去了。因此在子进程度stdout缓冲里面就也有了fork! 。所以,你最终看到的会是fork!  被printf了2次!!!!
        而运行printf("fork! /n")后,“fork!”被立即打印到了屏幕上,之后fork到的子进程里的stdout缓冲里不会有fork! 内容。因此你看到的结果会是fork! 被printf了1次!!!!

    #include <stdio.h>
    #include <unistd.h>
    
    int main()
    {
        fork();
        fork()&&fork()||fork();
        fork();
        printf("+
    ");
        return 0;
    }

    总共20个进程,除去main进程,还有19个进程

    第一个fork和最后一个fork肯定是会执行的。
        主要在中间3个fork上,可以画一个图进行描述。
        这里就需要注意&&和||运算符。
        A&&B,如果A=0,就没有必要继续执行&&B了;A非0,就需要继续执行&&B。
        A||B,如果A非0,就没有必要继续执行||B了,A=0,就需要继续执行||B。
        fork()对于父进程和子进程的返回值是不同的,按照上面的A&&B和A||B的分支进行画图,可以得出5个分支。

    http://blog.csdn.net/jason314/article/details/5640969

  • 相关阅读:
    正则表达式的语法表
    leetcode1567. 乘积为正数的最长子数组长度 吴丹阳
    leetcode152. 乘积最大子数组 吴丹阳
    leetcode740. 删除并获得点数 吴丹阳
    leetcode53. 最大子数组和 吴丹阳
    leetcode55. 跳跃游戏 吴丹阳
    leetcode45. 跳跃游戏 II 吴丹阳
    leetcode213. 打家劫舍 II 吴丹阳
    leetcode918. 环形子数组的最大和 吴丹阳
    leetcode482. 密钥格式化 吴丹阳
  • 原文地址:https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/5421284.html
Copyright © 2011-2022 走看看