热度 17
2015-3-9 15:31
1422 次阅读|
0 个评论
信号量(又名:信号灯)与其他进程间通信方式不大相同,主要用途是保护临界资源(进程互斥)。进程可以根据它判定是否能够访问某些共享资源。除了用于访问控制外,还可用于进程同步。 信号量的分类: 二值信号灯:信号灯的值只能取0或1 计数信号灯:信号灯的值可以取任意非负值。 信号量的实质:1、数字 2、操作,包括释放和获取两种情况。 8.1 创建 / 打开信号量集合 8.1.1 函数名 semget 8.1.2 函数原形 int semget(key_t key, int nsems, int sem***); 8.1.3 函数功能 获取信号量集合的标识符 8.1.4 所属头文件 sys/types.h sys/ipc.h sys/sem.h 8.1.5 返回值 成功:返回信号量集合的标识符 失败:-1 8.1.6 参数说明 key:键值 sem***:标志,可以取IPC_CREAT nsems:创建的这个信号量集合里面包含的信号量的数目 8.1.7 范例代码 8.2 操作信号量 8.2.1 函数名 semop 8.2.2 函数原形 int semop(int semid, struct *sops, unsigned nsops, struct timespec *timeout); 8.2.3 函数功能 操作信号量集里面的信号量 8.2.4 所属头文件 sys/types.h sys/ipc.h sys/sem.h 8.2.5 返回值 成功:返回0 失败:返回-1 8.2.6 参数说明 semid:要操作的信号量集合的标识符 nsops:要操作多少个信号量 sops:堆信号量执行什么样的操作,实则sops包含了下面这个结构体:其中sem_num:指定了是信号量集合的第几个信号量。sem_op:若sem_op为n。n0则表示释放了n个信号量。n0则表示获取了n个信号量 8.3 信号量的控制 8.3.1 函数名 semctl 8.3 .2 函数原形 int semctl(int semid, int semnum, int cmd, ...); 8.3 .3 函数功能 控制信号量 8.3 .4 所属头文件 sys/types.h sys/ipc.h sys/sem.h 8.3 .5 返回值 成功:根据cmd返回不同的非负值 失败:-1 8.3 .6 参数说明 semid:信号量集合的标识符 semnum:信号量集合的哪个信号量 cmd:相应的控制命令(GETVAL:返回成员semnum的semval值, SETVAL:设置成员semnum的semval值。该值由arg.val指定)。 8.4 获取key值 8.4.1 函数名 ftok 8.4 .2 函数原形 key_t ftok(const char *pathname, int proj_id); 8.4 .3 函数功能 将路径名和项目标识符转化为一个进程间信号量通信的key值 8.4 .4 所属头文件 sys/types.h sys/ipc.h 8.4 .5 返回值 成功:key值将被返回 失败:-1 8.4 .6 参数说明 pathname:路径名 proj_id:自定义的数字id 小实验:假设有这样的场景:数学课代表A要在公示栏上写“math cancel”这样一个通知。当他写完“math”后,电话铃响了。然后出去接了个电话。正在这时英语课代表B也要写通知,通知内容是“English exam”。这时公示栏上的内容是“math English exam”。B写完后,A又不管三七二十一的写上了“cancel”。这时黑板上的内容为“math English exam cancel”。从而引起了歧义。代码如下: astudent.c: #includestdio.h #includesys/types.h #includesys/stat.h #includefcntl.h int main() { int fd; fd = open("/home/board.txt",O_RDWR|O_APPEND);//读取txt文件 write(fd, "math", 5); sleep(3); write(fd, " cancel", 7); close(fd); return 0; } bstudent.c: #includestdio.h #includesys/types.h #includesys/stat.h #includefcntl.h int main() { int fd; fd = open("/home/board.txt",O_RDWR|O_APPEND);//读取txt文件 write(fd, "English exam", 13); return 0; } 公示栏上的内容为下图: 那么,怎样消除这样的问题呢?我们可以看出这两个事件是互斥的。我们可以通过设置一个信号量来解决。当A开始写通知的时候生成一个标志位。直至A写完通知,标志位状态改变,B开始写通知。 #includestdio.h #includesys/types.h #includesys/stat.h #includefcntl.h #includesys/types.h #includesys/ipc.h #includesys/sem.h int main() { int fd = 0; int semid; key_t key; struct sembuf sops; int ret; key = ftok("/home", 1); semid = semget(key, 1, IPC_CREAT); semctl(semid, 0, SETVAL, 1); fd = open("/home/board.txt",O_RDWR|O_APPEND);//读取txt文件 sops.sem_num = 0; sops.sem_op = -1; semop(semid, sops, 1); write(fd, "math", 5); sleep(10); write(fd, " cancel", 7); sops.sem_num = 0; sops.sem_op = 1; semop(semid, sops, 1); close(fd); return 0; } #includestdio.h #includesys/types.h #includesys/stat.h #includefcntl.h #includesys/types.h #includesys/ipc.h #includesys/sem.h int main() { int fd = 0; int semid; key_t key; struct sembuf sops; int ret; key = ftok("/home", 1); semid = semget(key, 1, IPC_CREAT); fd = open("/home/board.txt",O_RDWR|O_APPEND);//读取txt文件 sops.sem_num = 0; sops.sem_op = -1; semop(semid, sops, 1); write(fd, "English exam", 13); sops.sem_num = 0; sops.sem_op = 1; semop(semid, sops, 1); close(fd); return 0; }