fork两次然后在孙子进程中调用某函数避免孙子进程被kill掉产生僵尸进程
/*
这样做儿子进程很快就会退出,所以孙子进程不太可能产生僵尸进程,即使产生时间也极其短暂 */
#include <stdio.h>#include <stdlib.h>
#include <unistd.h>
void fork_grandson_run(void func(void));
void print_name(void);
int main(void)
{
int i;
for (i = 0; i < 10; i++) {
fork_grandson_run(print_name);
}
return 0;
}
void print_name(void)
{
// printf("my name is zhangbolun \n");
execlp("ls", "ls", "-a", NULL);
}
void fork_grandson_run(void func(void))
{
pid_t pid, pid2;
pid = fork();
if (pid < 0) {
perror("fork failed ");
exit(1);
} else if (pid == 0) { // son
pid2 = fork();
if (pid2 < 0) {
perror("fork failed ");
exit(1);
} else if (pid2 == 0) {
func();
exit(0);
} else {
exit(0);
}
} else { // parent
// do nothing
}
}
需要注意是:
wait()函数不能等待孙子进程,可以等待子进程
for(;wait((int*)0)>0;);这里的for循环的作用就是等到退出成功才往下运行,否则一直在等待;
共享内存的应用
/*共享内存申请标记*/
#define PERM S_IRUSR|S_IWUSR
/*孙子进程id号*/
pid_t gradchild;
/*子进程id号*/
pid_t pid;
/*共享内存描述标记*/
int shmid;
/*共享内存:用于存放子进程ID,播放列表位置*/
if((shmid = shmget(IPC_PRIVATE,5,PERM))== -1)
exit(1);//内存映射
p_addr = shmat(shmid,0,0);
/*内存映射*/
c_addr = shmat(shmid,0,0);
/*把孙子进程的id和当前播放歌曲的节点指针传入共享内存*/
memcpy(c_addr,&fd,sizeof(pid_t));
memcpy(c_addr + sizeof(pid_t)+1,¤tsong,4);
/*把孙子进程的pid传给父进程*/
memcpy(&gradchild,p_addr,sizeof(pid_t));
最后补充:共享内存是进程间通信(IPC)的一种。因为进程在使用共享内存时,可以直接读写内存,不需 要任何数据拷贝,所以它的效率是最高的。关于共享内存是内核专门留出来的一块内存,这段内存可以让访问的进程映射到自己的私有地址空间,从而可以操作共享 内存。 共享内存可以让不同的进程来映射地址,从而实现了进程之间的通信。
多个程序都来操作共享内存,需要一种同步机制,下面来介绍信号同步的机制。
共享内存的实现分为三步:第一步是创建共享内存,用的函数是shmget()函数;第二步是映射共享内存,用的函数是shmat();最后一步是撤销映射,用的函数是shmdt()。
建立好共享内存后,我是用信号来实现同步机制的,当然也可以用信号量等其他的。 使用信号需要了解kill()信号发送函数和signal()捕捉信号函数。首先kill函数需要知道对方进程的进程号,所以第一步就是获得对方的进程 号,可以通过共享内存获得。然后获得自己的进程号再通过共享内存发给对方。
这样当一个进程操作完以后,就可以发信号给另一个进程,实现了进程之间的同步。
可参考华清远见嵌入式学院免费课堂:http://www.embedu.org/lecture/