先这几天搞多进程以及多线程通信,怎奈以前没有深接触,所以这里总结一下。
#include <sys/types.h> #include <stdio.h> #include <stdlib.h> int glob = 6; char buf[] = "a write to stdout/n"; int main() { int var; pid_t pid; var = 88; fprintf(stderr, "%s", buf); printf("before fork/n"); if(( pid = fork() ) < 0 ) { fprintf(stderr, "fork error/n"); } else if(pid == 0) { glob++; var++; printf("child process/n"); printf("pid = %d, father pid = %d, glob = %d, var = %d/n", getpid(), getppid(), glob, var); exit(0); } else { sleep(2); printf("father process/n"); printf("pid = %d, father pid = %d, glob = %d, var = %d/n", getpid(), getppid(), glob, var); } return 0; }
运行结果为:
a write to stdout before fork child process pid = 5139, father pid = 5138, glob = 7, var = 89 father process pid = 5138, father pid = 2936, glob = 6, var = 88
为什么子进程没有修改全局变量和主进程的局部变量的值?
因为进程之间都是有独立的占用内存,子进程只是把父进程的相关变量值复制到了自己的变量中,所以这里修改的都是自己内存区域的变量的值。
为什么ifelse都执行了?
因为fork()之后出现了两个进程,而两个进程除了id不一样代码都是一样的,此时你就要把上面的代码想象成两份(实际就是两份),在主进程里面,fork()函数返回的是子进程的id,那么就执行else部分,而在子进程里面,fork返回的就是0。所以看上去就像是fork返回了两次值一样,实际是两份代码了。fork针对不同的进程返回不同的值。
还有一段代码
#include <stdlib.h> #include <unistd.h> #include <iostream> using namespace std; int j = 0; /* * */ int main(int argc, char** argv) { signal(SIGCHLD,SIG_IGN); //avoid zombie process int *i; i = &j; int k=0; pid_t pid,pid1,pid2; cout < <"this is at beginning, pointer i is" < <i < <endl; sleep(1); pid = fork(); if(pid <0) { cout < <"create childprocess error!" < <endl; } else if (pid == 0) { cout < <"for childprocess,pointer i = " < <i < <endl; for(k;k <10;k++) { (*i)++; cout < <"for childprocess,j = " < <*i < <endl; } } else if(pid > 0) { sleep(5); cout < <"for fatherprocess, j = " < <*i < <endl; cout < <"for fatherprocess, i = " < <i < <endl; } return (EXIT_SUCCESS); }
执行结果是:
this is at beginning, pointer i is0x804a0d4 for childprocess,pointer i = 0x804a0d4 for childprocess,j = 1 for childprocess,j = 2 for childprocess,j = 3 for childprocess,j = 4 for childprocess,j = 5 for childprocess,j = 6 for childprocess,j = 7 for childprocess,j = 8 for childprocess,j = 9 for childprocess,j = 10 for fatherprocess, j = 0 for fatherprocess, i = 0x804a0d4
可以看到指针指向的是相同的地址,为什么相同内存地址存储的数据是不一样的呢?
这是因为fork后两个进程有各自独立的内存空间,但是用的都是虚拟的内存空间,所以在子进程中的0x804a0d4地址与父进程的0x804a0d4虽然值相同,但是这是在自己的内存区域的值,并不是实际的物理内存的地址,当映射到物理内存以后实际上不同的区域。看看更专业的解释:
程序里看到的指针的值,比如0x804a0d4,都是虚拟地址。每个进程都有独立的4G的虚拟地址空间,映射到不同的物理空间。比如我现在同时运行IE和QQ,他们都有可能访问各自的0x804a0d4这个虚拟地址,但是映射之后的物理内存就不会是同一个地址。