需求:如何实现fork()后的子进程退出后,再退出父进程

    

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>


int main()
{
pid_t result;
int sem_id;

result=fork();
if(result==-1)
{
perror("fork\n");
}else if(result==0)
{
printf("chind process wait for some seconds ...\n");
sleep(5);
printf("The returned value is %d in the child process(pid=%d)\n",result,getpid());
}else{
//int status;
//wait(status);
printf("The return value is %d in the father process(pid=%d)\n",result,getpid());
}

return 0;
}


   上述代码,明显父进程先于子进程前退出

 

   解决方案一: 在父进程中调用 wait() 方法,堵塞等待子进程退出

   解决方案二: 利用信号量同步进程退出顺序. 

   



#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>


// 当semctl参数为4个时,必须手动定义这个联合体
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *_buf;
};


// 初始化信号量
int init_sem(int sem_id,int init_value)
{
union semun sem_union;
sem_union.val=init_value;
if(semctl(sem_id,0,SETVAL,sem_union)==-1)
{
perror("init semphore");
return -1;
}

return 0;
}

// 删除信号量
int del_sem(int sem_id)
{
union semun sem_union;
if(semctl(sem_id,0,IPC_RMID,sem_union)==-1)
{
perror("delete semphore");
return -1;
}

return 0;
}

// p操作获取资源
int sem_p(int sem_id)
{
struct sembuf sem_b;
sem_b.sem_num = 0; // 单个信号量
sem_b.sem_op = -1; // -1表p操作
sem_b.sem_flg=SEM_UNDO; // 在进程退出时,自动释放信号量

if(semop(sem_id,&sem_b,1)==-1)
{
perror("p operation");
return -1;
}

return 0;
}

// v操作释放资源
int sem_v(int sem_id)
{
struct sembuf sem_b;
sem_b.sem_num = 0; // 信号量编号, 单个信号量
sem_b.sem_op = 1; // +1表V操作
sem_b.sem_flg=SEM_UNDO; // 在进程退出时,自动释放信号量

if(semop(sem_id,&sem_b,1)==-1)
{
perror("v operation");
return -1;
}

return 0;
}


int main(int argc,char **argv)
{
pid_t result;
int sem_id;

// key_t key=ftok() 产生唯一ipc键
sem_id=semget(ftok(".",'a'),1,0666|IPC_CREAT);
init_sem(sem_id,0); // 设置信号量为0

result=fork();
if(result==-1)
{
perror("fork\n");
}else if(result==0) // 子进程
{
printf("chind process wait for some seconds ...\n");
sleep(5);
printf("The returned value is %d in the child process(pid=%d)\n",result,getpid());
sem_v(sem_id); // v操作,资源数+1
}else{ // 父进程
sem_p(sem_id); // 此时资源计数为0,堵塞等待子进程释放资源,当资源数>0时才向下执行
printf("The return value is %d in the father process(pid=%d)\n",result,getpid());
sem_v(sem_id);
del_sem(sem_id);
}

return 0;
}