欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux 信号量

程序员文章站 2022-07-13 16:44:11
...

    需求:如何实现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;
}

    详见: http://blog.csdn.net/mybelief321/article/details/9086151

 

 

 

 

相关标签: fork 信号量