Linux系统编程(有名信号量)

在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量。无名信号量一般用于线程间同步或互斥,而有名信号量一般用于进程间同步或互斥。它们的区别和管道及命名管道的区别类似,无名信号量则直接保存在内存中,而有名信号量要求创建一个文件。

1)创建一个有名信号量

所需头文件:

#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>

当有名信号量存在时使用:

sem_t *sem_open(const char *name, int oflag);

当有名信号量不存在时使用:

sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);

功能:

创建一个有名信号量。

参数:

name:信号量文件名。注意,不能指定路径名。因为有名信号量,默认放在/dev/shm 里。
flags:sem_open() 函数的行为标志。
mode:文件权限(可读、可写、可执行)的设置。
value:信号量初始值。

返回值:

成功:信号量的地址
失败:SEM_FAILED

2)关闭有名信号量
所需头文件:

#include <semaphore.h>
int sem_close(sem_t *sem);

功能:

关闭有名信号量。

参数:

sem:指向信号量的指针。

返回值:

成功:0
失败:-1

3)删除有名信号量文件

所需头文件:

所需头文件:
#include <semaphore.h>
int sem_unlink(const char *name);

功能:

删除有名信号量的文件。

参数:

name:有名信号量文件名。

返回值:

成功:0
失败:-1

4)信号量 PV 操作

有名信号量实现进程间互斥功能:


#include<stdio.h>
#include<semaphore.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include <sys/wait.h>
void printer(sem_t *sem, char *str)
{

	sem_wait(sem);	//信号量减一

	while(*str!='\0')
	{

		putchar(*str);	
		fflush(stdout);
		str++;
		sleep(1);
	}

	printf("\n"); 

	sem_post(sem);	//信号量加一

}

int main(int argc, char *argv[])
{

	pid_t pid;
	sem_t *sem = NULL;
	pid = fork(); //创建进程
	if(pid<0){ //出错
		perror("fork error");
	}else if(pid == 0){ //子进程
		//跟open()打开方式很相似,不同进程只要名字一样,那么打开的就是同一个有名信号量
		sem = sem_open("name_sem", O_CREAT|O_RDWR, 0666, 1); //信号量值为 1
		if(sem == SEM_FAILED){ //有名信号量创建失败
			perror("sem_open");
			return -1;

		}
		char *str1 = "hello";
		printer(sem, str1); //打印
		sem_close(sem); //关闭有名信号量
		_exit(1);

	}else if(pid > 0){ //父进程
		//跟open()打开方式很相似,不同进程只要名字一样,那么打开的就是同一个有名信号量
		sem = sem_open("name_sem", O_CREAT|O_RDWR, 0666, 1); //信号量值为 1
		if(sem == SEM_FAILED){//有名信号量创建失败
			perror("sem_open");
			return -1;

		}
		char *str2 = "world";
		printer(sem, str2); //打印
		sem_close(sem); //关闭有名信号量
		wait(NULL); //等待子进程结束

	}
	sem_unlink("name_sem");//删除有名信号量
	return 0;

}

在这里插入图片描述

有名信号量实现进程间同步功能(print2 先打印,再到 print1 打印):

print1.c 代码如下:


#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>
#include <stdio.h>

 

void print(sem_t *print1, sem_t *print2)
{
	int i = 0;
	while(1)
	{
		sem_wait(print1);
		i++;
		printf("int print1 i = %d\n", i);
		sem_post(print2);
	}

}

 

int main(int argc, char **argv)
{	

	sem_t *print1, *print2;
	print1 = sem_open("sem_print1", O_CREAT, 0777, 0);  
	if(SEM_FAILED == print1)
	{
		perror("sem_open");
	}

	print2 = sem_open("sem_print2", O_CREAT, 0777, 1);    
	if(SEM_FAILED == print2)
	{
		perror("sem_open");
	}
	print(print1, print2);
	return 0;

}

print2.c 代码如下:


#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>
#include <stdio.h>


void print(sem_t *print1, sem_t *print2)
{
	int i = 0;
	while(1)
	{
		sem_wait(print2);
		i++;
		printf("in print2 i = %d\n", i);
		sleep(1);
		sem_post(print1);
	}

}

 

int main(int argc, char **argv)
{	

	sem_t *print1, *print2;
	print1 = sem_open("sem_print1", O_CREAT, 0777, 0);  
	if(SEM_FAILED == print1)
	{
		perror("sem_open");
	}


	print2 = sem_open("sem_print2", O_CREAT, 0777, 1);  
	if(SEM_FAILED == print2)
	{
		perror("sem_open");
	}
	print(print1, print2);
	return 0;

}

在这里插入图片描述

删除有名信号量示例代码如下:


#include <semaphore.h>
#include <stdio.h>

void sem_del(char *name)
{

	int ret;
	ret = sem_unlink(name);
	if(ret < 0)
	{
		perror("sem_unlink");
	}

}

 

int main(int argc, char **argv)
{
	sem_del("sem_print1"); //删除信号量文件sem_print1
	sem_del("sem_print2"); //删除信号量文件sem_print2
	return 0;

}


(学习复习资料)本来内容来自:https://blog.csdn.net/tennysonsky/article/details/45847107

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值