【Linux信号通讯编程】信号量互斥编程

一、信号量(semaphore)

        在进程互斥中,信号量主要用来保护临界资源。进程通过信号量来判断

是否能够访问该共享资源。(当然,后面我们还会用来控制进程同步)。


二、信号量类型

1、二值信号量:信号量的取值为 0 或者 1

2、计数信号量:信号量的取值为任意非负数


三、键值 : 文件标示符 + 项目ID

1、任意指定一个数:若该数已被使用,则不能与信号量关联(失败)

2、构造一个数:使用ftok()构造

3、了解键值: 来自新浪博客 路在脚下 深入解读键值产生原理,linux中的软链接和硬链接


四、函数学习


1、创建 / 打开信号量集合:semget

1)函数原型

int semget(key_t key, int nsems, int semflg);

2)所属头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

3)返回值

成功: 返回信号量集合标识符(非负整数); 当信号量<0时访问该信号量的其他进程等待

失败: -1

4)参数说明

key: 信号量的键值

nsems: 信号量的数目

semflg: 同open()函数的权限位


2、操作信号量:semop

1)函数原型

int semop(int semid, struct sembuf *sops, unsigned nsops);

2)所属头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

3)返回值

成功: 0

失败: -1

4)参数说明

semid: 要操作的信号量集合的标识符

sops: 对信号量执行什么操作

nsops: 要操作的信号量数目

struct sembuf sops{

unsigned short sem_num;  /* 信号量序号 */

short          sem_op;   /* 对信号量操作 */

short          sem_flg;  /* operation flags */

}


3、键值转换:ftok

1)函数原型

key_t ftok(const char *pathname, int proj_id);

2)所属头文件

#include <sys/types.h>

#include <sys/ipc.h>

3)返回值

成功: 返回生成的键值

失败: -1

4)参数说明

pathname: 包含路径的文件名

proj_id: 项目序号


4、信号量控制操作:semctl

1)函数原型 

int semctl(int semid, int semnum, int cmd, ...);

2)所属头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

3)返回值 

成功: 返回一个非负整数(取决于cmd)

失败: -1

4)参数说明

semid: 信号量集合

semnum: 集合中的信号量序号

cmd: 命令


* 最佳实践  - 1:

/* op_1.c */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>

#define FILE_NAME "./BOARD.TXT"

void main()
{
	int fd = 0;
	key_t key = 0;
	int semid = 0;
	int sem_val = 0;
	struct sembuf sops;

	/* 创建键值. */
	key = ftok("/home/taylor/linux-3/signal-process/BOARD.TXT",1);

	/* 创建并打开信号量集合. */
	semid = semget(key, 1, IPC_CREAT);
	
	/* 设置信号量初值为1.默认不为0 */
	sem_val = semctl(semid, 0, SETVAL, 1);

	printf("Semaphore init value is : %d\n", sem_val);

	/* 打开信息文件. */
	fd = open(FILE_NAME, O_RDWR | O_APPEND);

	/* 获取信号量.*/
	sops.sem_num = 0;
	sops.sem_op = -1;
	semop(semid, &sops, 1);

	/* 插入数据. */
	write(fd, "I Love ", 7);

	sleep(10);  //等待, 这里运行op_2, 检测是否互斥

	write(fd, "You.", 4);

	/* 释放信号量. */
	sops.sem_num = 0;
	sops.sem_op = 1;
	semop(semid, &sops, 1);

	/* 关闭文件. */
	close(fd);
}


* 最佳实践 - 2:

/* op_2.c */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>

#define FILE_NAME "./BOARD.TXT"

void main()
{
	int fd = 0;
	key_t key = 0;
	int semid = 0;
	int sem_num = 0;
	struct sembuf sops;

	/* 创建键值. */
	key = ftok("/home/taylor/linux-3/signal-process/BOARD.TXT",1);
	
	/* 打开信号量集合. */
	semid = semget(key, 1, IPC_CREAT);

	/* 获取信号量初始化. */
	sem_num = semctl(semid, 0, GETVAL);

	printf("Student2 get init value is: %d\n", sem_num);

	/* 打开信息文件. */
	fd = open(FILE_NAME, O_RDWR | O_APPEND);

	/* Get semaphore. */
	sops.sem_num = 0;
	sops.sem_op = -1;  //当信号量<0时, 执行等待
	semop(semid, &sops, 1);

	/* 插入信息,看看是否插队op_1 */
	write(fd, "pig is you ", 11);

	/* Release semaphore. */
	sops.sem_num = 0;
	sops.sem_op = 1;
	semop(semid, &sops, 1);

	close(fd);
}

输出:

* 先后台运行op_1 # ./op_1 &

* 再运行op_2 # ./op_2

* 从结果可以看出, 若在sleep(10)等待时没有互斥现象, 则输出内容为: I Love pig is you You. 信息将错乱





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值