Linux信号量使用心得总结(system)

应用程信号量有Posix信号量和SYSTEM信号,本文讨论的是SYSTEM V信号量,SYSTEM V信号量是SYSTEM V进程间通信的组成部分。SYSTEM V进程间通信包括:信号量,消息队列,共享内存。

函数包括如下:

 

先看一个有问题的代码,以下代码中,目的是实现父进程和子进程的对临界区资源访问的互斥,使对临界区资源的操作具有原子性,但实际运行中,并未实现父进程和子进程的互斥。SEM_UNDO的意思是当持有信号量的进程退出后,将自动释放信号量防止死锁。程序中父进程或子进程执行P操作后持有信号量,但进程很快结束退出,导致信号量被释放了,所有另一个进程执行P操作的时候没有阻塞。

 

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
union semun
{
	int val;
	struct semid_ds *buf;
	unsigned short *array;


};



int sem_init(int sem_id, int init_valve)
{
	union semun sem_union;
	sem_union.val = init_valve; //初始化信号量的值

	if( semctl(sem_id, 0, SETVAL, sem_union) )
	{
		perror("Initinal semaphore");
		return -1;
	}
	return 0;

}


int sem_v(int sem_id)
{
	struct sembuf sem_b;
	sem_b.sem_num = 0; //信号量编号
	sem_b.sem_op = 1;
	sem_b.sem_flg = SEM_UNDO;

	printf("v start\n");
	if( semop(sem_id, &sem_b, 1)==-1 )
	{
		perror("V operation");
		return -1;
	}
	printf("v end\n");
	return 0;
}

int sem_p(int sem_id)
{
	struct sembuf sem_b;
	sem_b.sem_num = 0;
	sem_b.sem_op = -1;
	sem_b.sem_flg = SEM_UNDO;
	
	printf("p start\n");
	if( semop(sem_id, &sem_b, 1)==-1 )
	{
		perror("P operation\n");
		return -1;
	}
	printf("p end\n");
	
	return 0;

}

int main()
{
	pid_t pid;
	int sem_id;

	sem_id = semget(ftok(".", 'a'), 1, 0666|IPC_CREAT );
	sem_init(sem_id, 1);  //初始化信号量的值

	printf("sem_id:%d\n", sem_id);
	pid = fork();
	if(pid == -1)
	{
		perror("fork\n");
	}
	else if( pid == 0) //子
	{
		
		printf("sem_id:%d\n", sem_id);
		sem_p(sem_id);
		printf("child progress, pid=%d\n", getpid());
		
		//sem_v(sem_id);		
	}
	else //父
	{
		sleep(1);
		sem_p(sem_id); //为什么不阻塞?
		printf("farther pid=%d\n", getpid());
		//sem_v(sem_id);
	}


	return 0;
}





对main函数的修改如下,实现了父进程和子进程的互斥。信号量的初始值为1,当子进程进行P操作后睡眠,父进程执行P操作时加阻塞,直到子进程执行V操作释放了信号量。


int main()
{
	pid_t pid;
	int sem_id;

	sem_id = semget(ftok(".", 'a'), 1, 0666|IPC_CREAT );
	sem_init(sem_id, 1);  //初始化信号量的值

	printf("sem_id:%d\n", sem_id);
	pid = fork();
	if(pid == -1)
	{
		perror("fork\n");
	}
	else if( pid == 0) //子
	{
		int i;
		for(i=0; i<10; i++) {
			printf("sem_id:%d\n", sem_id);
			sem_p(sem_id, getpid());
			printf("child progress, pid=%d\n", getpid());
			sleep(1);
			sem_v(sem_id,getpid());	
			sleep(1);
		}
	}
	else //父
	{
		//sleep(10);
		int i;
		for(i=0; i<10; i++) {
			sem_p(sem_id, getpid()); //
			printf("farther pid=%d\n", getpid());
		    sleep(1);
			sem_v(sem_id, getpid());

			sleep(1);
		}
	}


	return 0;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值