Linux进程共享

来源:互联网 发布:驱动精灵mac版官网 编辑:程序博客网 时间:2024/05/16 09:30

进程共享

父子进程之间在fork后。有哪些相同,那些相异之处呢?

fork之后:

父子相同处: 全局变量、.data.text、栈、堆、环境变量、用户ID、宿主目录、进程工作目录、信号处理方式...

父子不同处: 1.进程ID   2.fork返回值   3.父进程ID    4.进程运行时间    5.闹钟(定时器)   6.未决信号集

似乎,子进程复制了父进程0-3G用户空间内容,以及父进程的PCB,但pid不同。真的每fork一个子进程都要将父进程的0-3G地址空间完全拷贝一份,然后在映射至物理内存吗?

当然不是!父子进程间遵循读时共享写时复制的原则。这样设计,无论子进程执行父进程的逻辑还是执行自己的逻辑都能节省内存开销。   

练习:编写程序测试,父子进程是否共享全局变。     fork_shared.c

重点注意!躲避父子进程共享全局变量的知识误区!

【重点】:父子进程共享:1. 文件描述符(打开文件的结构体)  2. mmap建立的映射区(进程间通信详解)



#include <stdio.h>  #include <stdlib.h>  #include <unistd.h>  #include <pthread.h>    int golobal_a = 0;    int main()  {      int local_a = 0;      pthread_mutex_t local_mutex_a;      pthread_mutex_t local_mutex_b;      pid_t pid;        pthread_mutex_init(&local_mutex_a, NULL);      pthread_mutex_init(&local_mutex_b, NULL);      pid = fork();        if(pid > 0) {          printf("father %d, child %d\n", getpid(), pid);          local_a = 1;          golobal_a = 1;          sleep(1);          printf("father local_a %d, addr %p, golobal_a %d, addr %p\n", local_a, &local_a, golobal_a, &golobal_a);            pthread_mutex_lock(&local_mutex_a);          printf("father lock mutex a %p\n", &local_mutex_a);          sleep(1);          pthread_mutex_lock(&local_mutex_b);          printf("father lock mutex b %p\n", &local_mutex_b);          pthread_mutex_unlock(&local_mutex_b);          pthread_mutex_unlock(&local_mutex_a);      } else if (pid == 0) {          printf("child %d\n", getpid());          local_a = 2;          golobal_a = 2;          sleep(1);          printf("child local_a %d, addr %p, golobal_a %d, addr %p\n", local_a, &local_a, golobal_a, &golobal_a);            pthread_mutex_lock(&local_mutex_b);          printf("child lock mutex b %p\n", &local_mutex_b);          sleep(1);          pthread_mutex_lock(&local_mutex_a);          printf("child lock mutex a %p\n", &local_mutex_a);          pthread_mutex_unlock(&local_mutex_a);          pthread_mutex_unlock(&local_mutex_b);      } else          printf("fork fail\n");        return 0;  }  


fork之后,子进程会拷贝父进程的数据空间、堆和栈空间(实际上是采用写时复制技术),二者共享代码段。

所以在子进程中修改全局变量(局部变量,分配在堆上的内存同样也是)后,父进程的相同的全局变量不会改变。
father 17164, child 17165  child 17165  father local_a 1, addr 0x7fff1793d298, golobal_a 1, addr 0x601070  father lock mutex a 0x7fff1793d2a0  child local_a 2, addr 0x7fff1793d298, golobal_a 2, addr 0x601070  child lock mutex b 0x7fff1793d2d0  father lock mutex b 0x7fff1793d2d0  child lock mutex a 0x7fff1793d2a0  

程序正常退出,没有发生死锁,说明不管是局部的还是全局的变量或者是锁,fork()之后,子进程都拥有了一份父进程的拷贝。

虽然变量和锁的虚拟地址都是一样的,但是物理上是两个不同的内存地址,两个进程之间完全不受影响。



0 0
原创粉丝点击