zoukankan      html  css  js  c++  java
  • 【转】Linux fork操作之后发生了什么?又会共享什么呢?

    原文: https://www.bbsmax.com/A/n2d99QxBdD/

    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <string.h>
    #include <fcntl.h>
    #include <iostream>
    
    using namespace std;
    static int global_val = 0;
    int main()
    {
      int *p = (int*)malloc(sizeof(int));
      *p=0;
      int m = 2;
      pid_t pid ;
      int fd = open("mytest", O_RDWR | O_CREAT, 0666);
      if ((pid = fork()) < 0)
      {
        cout << "fork error" << endl;
      }
      else {
        if (pid == 0)
        {
          char buf[20]="";
          int res = read(fd,buf,20);
          cout<<"ppid is "<<getppid()<<" pid is "<<getpid()<<" res is "<<res<<" fd is "<<fd<<" buf is "<< buf<<endl;
          //close(fd);
          //sleep(1);
    
          char bufs[8]="shenlei";
          lseek(fd, 0, SEEK_SET);
          write(fd,bufs,strlen(bufs));
    
          // read
          char nbuf[20]="";
          lseek(fd, 0, SEEK_SET);
          int nres = read(fd,nbuf,20);
          cout<<"after write file: "<<nbuf<<" nres:"<<nres<<endl;
          global_val++;
          m++;
          (*p)++;
        }else{
          sleep(2);
          char buf[20]="";
          lseek(fd, 0, SEEK_SET);
          int res = read(fd,buf,20);
           cout<<"parent ppid is "<<getppid()<<" pid is "<<getpid()<<" res is "<<res<<" fd is "<<fd<<" buf is "<< buf<<endl;
           cout << *p << " " << m << " " << global_val<< endl;
           }
       }
       return 0;
     }
    

      

    ----------------------------

    今天我在阅读《Unix网络编程》时候遇到一个问题:accept返回时的connfd,是父子进程之间共享的?我当时很不理解,难道打开的文件描述符不是应该在父子进程间相互独立的吗?为什么是共享的呢?fork之后父子进程之间共享了什么?堆上的变量是否也共享了呢?

      做了如下的代码测试,在fork之前先创建一个文件,在子进程中写入字符串“shenlei”,父进程读取文件内容,发现也是“shenlei”。说明打开的文件描述符在父子进程之间是共享的。另一方面,在父子进程中读取文件描述符fd,发现二者相等,进一步证实了这个观点。

      看来在《Unix网络编程》中说的是对的,当close一个文件描述符时候会将文件描述符的引用计数-1。在普通文件io操作时,只有当引用计数为0才能真正关闭该文件描述符;在socket操作时,也只有当引用计数为0时才会发送FIN,四次挥手关闭相应的socket。

    1. #include <unistd.h>
    2. #include <stdlib.h>
    3. #include <sys/types.h>
    4. #include <sys/stat.h>
    5. #include <string.h>
    6. #include <fcntl.h>
    7. #include <iostream>
    8.  
    9. using namespace std;
    10. static int global_val = 0;
    11. int main()
    12. {
    13. int *p = (int*)malloc(sizeof(int));
    14. *p=0;
    15. int m = 2;
    16. pid_t pid ;
    17. int fd = open("mytest", O_RDWR | O_CREAT, 0666);
    18. if ((pid = fork()) < 0)
    19. {
    20. cout << "fork error" << endl;
    21. }
    22. else {
    23. if (pid == 0)
    24. {
    25. char buf[20]="";
    26. int res = read(fd,buf,20);
    27. cout<<"pid is "<<getpid()<<" res is "<<res<<" fd is "<<fd<<" buf is "<< buf<<endl;
    28. close(fd);
    29. //sleep(1);
    30. char bufs[8]="shenlei";
    31. lseek(fd, 0, SEEK_SET);
    32. write(fd,bufs,strlen(bufs));
    33. global_val++;
    34. m++;
    35. (*p)++;
    36. }
    37. else{
    38. sleep(1);
    39. char buf[20]="";
    40. lseek(fd, 0, SEEK_SET);
    41. int res = read(fd,buf,20);
    42. cout<<"pid is "<<getpid()<<" res is "<<res<<" fd is "<<fd<<" buf is "<< buf<<endl;
    43. cout << *p << " " << m << " " << global_val<< endl;
    44. }
    45. }
    46. return 0;
    47. }

      然后又测试了下,一个进程中的堆对象能否共享,如上述代码所示,结论是不可以的。全局变量,静态变量,全局静态变量也都是不行的。说明在fork创建多进程之后堆栈信息会完全复制给子进程内存空间,父子进程相互独立。

  • 相关阅读:
    oracle如何实现自增?----用序列sequence的方法来实现
    win7旗舰版安装 oracle 10g 不能进入图形界面的问题
    MBA都需要学习哪些课程
    查看Oracle当前用户下的(表视图,同义词...)
    辽宁省全国计算机等级考试 网上报名须知
    大学毕业之后的几年 你能考哪些证书
    plsql启动报 Using filter for all users can lead to poor perform
    hive web界面管理
    hive常用命令
    hive-site.xml
  • 原文地址:https://www.cnblogs.com/oxspirt/p/14759451.html
Copyright © 2011-2022 走看看