fork()父子进程变量之间的关系与信号的响应
2015-01-30 10:48
525 查看
1.变量关系:
根据《unix 高级环境编程》中的一句话:子进程和父进程继续执行fork调用之后的指令。子进程是父进程的副本。例如:子进程获取父进程数据空间,堆和栈的副本。注意,这是子进程所拥有的副本。父子进程并不共享这些存储空间部分。父子进程共享正文段(就是代码段.text)。
个人理解:就是说一子进程会复制父进程的数据,但是这些数据是存放在另一个地方的,双方的数据都是对自己可见而已,你不可能通过一个变量来进行双方的通信!!!
下面来做个小测试,关于变量的可见性:
测试结果:
从结果可以看出来:子进程修改的值并没有对父进程有影响。但是变量的地址都是一样的,数据却是不一样的。怎么理解。。。。。个人觉得吧,物理地址一定是一样的,但是它们的逻辑地址是不一样的,就是进程的虚拟地址是不一样的,不知道对不对,先这样觉得吧。
2.信号响应
对于父子进程,都能响应信号,但是,如果我发一个SIGINT信号一次,那么父子进程都响应这个信号(前提是父子进程都注册了这个信号响应)吗?另外信号处理程序只有一个,父子进程是共享的,那么,当父子进程分别响应信号时,是否在各自的进程领域内?
从第一点来看,父子进程正文段是共享的,但数据存储区并不是共享的,那么数据是属于进程领域内的。
那么问题是什么?这里想验证一下,同一个信号响应处理程序是不是对父子的调用是独立的。
测试代码:
说明:
测试程序流程:子进程先休眠10s,在这个过程任何信号可唤醒子进程。父进程等待子进程结束,而这个过程接收任意信号。
测试结果:
[root@localhost src]# ./sig_main
wait child,father pid=8065
start child pid = 8066
^CSIGINT catch
in handle pid = 8066
child exit
SIGCHLD catch
in handle pid = 8065
wait child succeed
SIGINT catch
in handle pid = 8065
father exit,getchild pid:8066
[root@localhost src]#
NOTE:
上面的^C 是crtl+c 发送一个SIGINT信号
一个SIGINT信号,父子进程都接收了,并且是分别接收的,从PID就可以看出来。
根据《unix 高级环境编程》中的一句话:子进程和父进程继续执行fork调用之后的指令。子进程是父进程的副本。例如:子进程获取父进程数据空间,堆和栈的副本。注意,这是子进程所拥有的副本。父子进程并不共享这些存储空间部分。父子进程共享正文段(就是代码段.text)。
个人理解:就是说一子进程会复制父进程的数据,但是这些数据是存放在另一个地方的,双方的数据都是对自己可见而已,你不可能通过一个变量来进行双方的通信!!!
下面来做个小测试,关于变量的可见性:
volatile int g_val = 0; int main() { int val = 0; pid_t fpid; printf("\nprocess\tpid\tppid\tcpid\tval\tval_address\tg_val\tg_val_address \n"); printf("%s\t%d\t%d\t \t%d\t%x\t%d\t%x\n","main",getpid(),getppid(),val,&val,g_val,&g_val); if ((fpid = fork()) < 0) printf("fork error\n"); else if (0 == fpid)//child { val++; g_val++; printf("%s\t%d\t%d\t%d\t%d\t%x\t%d\t%x\n","child",getpid(),getppid(),fpid,val,&val,g_val,&g_val); } else//father { sleep(5);//wait for child exit,and we can sure the variable has changed but maybe the result is not like what we think it is. //printf("father wakes up\n"); printf("%s\t%d\t%d\t%d\t%d\t%x\t%d\t%x \n","father",getpid(),getppid(),fpid,val,&val,g_val,&g_val); } return 0; }
测试结果:
[root@localhost src]# ./sig_main process pid ppid cpid val val_address g_val g_val_address main 2976 2698 0 bfcd7ce8 0 8049138 child 2977 2976 0 1 bfcd7ce8 1 8049138 father 2976 2698 2977 0 bfcd7ce8 0 8049138 [root@localhost src]#
从结果可以看出来:子进程修改的值并没有对父进程有影响。但是变量的地址都是一样的,数据却是不一样的。怎么理解。。。。。个人觉得吧,物理地址一定是一样的,但是它们的逻辑地址是不一样的,就是进程的虚拟地址是不一样的,不知道对不对,先这样觉得吧。
2.信号响应
对于父子进程,都能响应信号,但是,如果我发一个SIGINT信号一次,那么父子进程都响应这个信号(前提是父子进程都注册了这个信号响应)吗?另外信号处理程序只有一个,父子进程是共享的,那么,当父子进程分别响应信号时,是否在各自的进程领域内?
从第一点来看,父子进程正文段是共享的,但数据存储区并不是共享的,那么数据是属于进程领域内的。
那么问题是什么?这里想验证一下,同一个信号响应处理程序是不是对父子的调用是独立的。
测试代码:
<pre name="code" class="cpp">volatile int flag = 0; void myhandler(int signo) { pid_t fpid; if (SIGUSR1 == signo) printf("receive SIGUSER1\n"); else if (SIGUSR2 == signo) printf("receive SIGUSER2\n"); else if ( SIGALRM == signo) { fpid = getpid(); printf("pid = %d\n",fpid); alarm(2); } else if (SIGINT == signo) { printf("SIGINT catch\n"); fpid = getpid(); printf("in handle pid = %d\n",fpid); } else if (SIGCHLD == signo) { printf("SIGCHLD catch\n"); fpid = getpid(); printf("in handle pid = %d\n",fpid); flag = 1; printf("wait child succeed\n"); } else printf("received signal %d\n",signo); //printf("alarm handler\n"); } int main() { pid_t fpid; sigset_t newmask,oldmask,waitmask; /*为父子进程同时注册信号*/ if (signal(SIGUSR2,myhandler) == SIG_ERR) printf("can't catch SIGUSER2"); if (signal(SIGUSR1,myhandler) == SIG_ERR) printf("can't catch SIGUSER1"); if (signal(SIGALRM,myhandler) == SIG_ERR) printf("can't catch SIGUSER1"); if (signal(SIGQUIT,myhandler) == SIG_ERR) printf("can't catch SIGQUIT"); if (signal(SIGINT,myhandler) == SIG_ERR) printf("can't catch SIGQUIT"); if (signal(SIGCHLD,myhandler) == SIG_ERR) printf("can't catch SIGCHLD"); sigemptyset(&waitmask); fpid = fork(); if (0 == fpid)//child { printf("start child pid = %d\n",getpid()); //sigaddset(&newmask,SIGINT); //sigprocmask(SIG_BLOCK,&newmask,&oldmask);//子进程不接收中断信号 sleep(10); printf("child exit\n"); } else//father { printf("wait child,father pid=%d\n",getpid()); while (flag == 0)//这样做是因为这期间可能会有很多信号到来,然后sigsuspend会被唤醒,但这并是我想要的信号,所以等。 sigsuspend(&waitmask); fpid = wait(); flag = 0; printf("father exit,getchild pid:%d \n ",fpid); } return 0; }
说明:
测试程序流程:子进程先休眠10s,在这个过程任何信号可唤醒子进程。父进程等待子进程结束,而这个过程接收任意信号。
测试结果:
[root@localhost src]# ./sig_main
wait child,father pid=8065
start child pid = 8066
^CSIGINT catch
in handle pid = 8066
child exit
SIGCHLD catch
in handle pid = 8065
wait child succeed
SIGINT catch
in handle pid = 8065
father exit,getchild pid:8066
[root@localhost src]#
NOTE:
上面的^C 是crtl+c 发送一个SIGINT信号
一个SIGINT信号,父子进程都接收了,并且是分别接收的,从PID就可以看出来。
相关文章推荐
- fork 父子进程变量之间的关系
- Linux中fork()函数详解 父子进程变量的关系
- 创建进程 fork()函数的基本使用 父子进程之间的关系
- 信号实现父子进程之间的同步--sigsuspend的作用
- fork - 利用信号在父子进程间传递指针的实验
- 关于fork函数生成父子进程变量虚拟地址
- 信号实现父子进程之间的同步--sigsuspend的作用
- fork之后父子进程的内存关系
- 信号实现父子进程之间的同步--sigsuspend的作用
- 使用pipe()与fork()函数通过管道实现父子进程之间的通信
- 关父子进程关系fork()
- Linux报错-bash: fork: retry: Resource temporarily unavailable和进程描述符之间的关系
- fork()后 父子进程变量地址一致
- 信号实现父子进程之间的同步--sigsuspend的作用
- malloc 之后的父子进程之间的空间关系如何
- 父子进程之间的关系
- malloc()后进行fork()系统调用,父子进程空间关系如何
- 关父子进程关系fork()
- fork()后,父子进程变量地址相同?
- fork()后父子进程间的变量共享情况