linux进程通信-信号量

来源:互联网 发布:tcp端口怎么打开 编辑:程序博客网 时间:2024/06/07 03:44

信号灯

1.     信号量

(1)概念

信号量(又名:信号灯)与其他进程间通信方式不大相同,主要用途是保护临界资源.

进程可以根据它判定是否能够访问某些共享资源。除了用于访问控制外,还可用于进程同步。

(2)分类

二值信号灯:信号灯的值只能取0或1,类似于互斥锁。 但两者有不同:

信号灯强调共享资源,只要共享资源可用,其他进程同样可以修改信号灯的值;

互斥锁更强调进程,占用资源的进程使用完资源后,必须由进程本身来解锁。

   计数信号灯:信号灯的值可以取任意非负值

(3)步骤

a)       创建打开信号量,semget()

b)       初始化信号量,semctl()SETVAL操作。使用二维信号量时将信号量初始化为1;

c)       进行信号量的PV操作,调用semop()函数。

d)       如果不用信号量,从系统中删除他/她,使用semctl的IPC_RMID操作。

 

2.     内核实现信号灯的原理及其API函数

(1)semget

函数的作用:创建信号量

函数的原型:int semget(key_t key,int nsems,int semflg);

函数的参数:nsems:创建信号量的数目,通常取1个

            semflg:同open一样的权限

返回值:成功:信号量的标识符;出错:-1

(2)semctl

函数的作用:信号量的控制:初始化、删除等

函数的原型:int semctl(int semid,int semnum,int gmd,union semun arg);

函数的参数:semnum:通常为0,第一个信号量

            cmd:IPC_STAT:获取结构量

                IPC_SETVAL:设置为arg中的val值

                IPC_GETVAL:获取信号量的值

                IPC_RMID:从系统中删除信号量

            arg:union semun结构

返回值:cmd不同的返回值不同

    IPC_STAT、IPC_SETVAL、IPC_RMID、返回值为0;IPC_GETVAL:返回信号量的值;出错为-1

(3)semop

函数的作用:执行PV操作

函数的原型:int semop(int semid,struct sembuf * sops,size_t nsops);

函数的参数:semid:semget()函数返回的信号量标识符

            sops:指向信号量操作数组

            struct sembuf *sops;

            sem_op:-1为P操作;+1为V操作

            nsops:操作信号量的个数

返回值:成功:信号量标识符;出错:-1

 

3.     如何使用信号灯来实现进程间的同步与互斥?

信号量的同步和互斥PV(见下例)

sem1.c

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <sys/ipc.h>#include <sys/sem.h>int main(){    int fd = 0;    key_t key;    int semid;    struct sembuf sops;    int ret;    key = ftok("/home/linux/", 1);    semid = semget(key, 1, IPC_CREAT);    ret = semctl(semid, 0, SETVAL, 1);    fd = open("borad.txt", O_RDWR | O_CREAT | O_APPEND);    sops.sem_num = 0;    sops.sem_op = -1;    semop(semid, &sops, 1);    write(fd, "class math", 11);    sleep(20);    sops.sem_num = 0;    sops.sem_op = +1;    semop(semid, &sops, 1);    close(fd);    return 0;}

sem2.c

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <sys/ipc.h>#include <sys/sem.h>int main(){    int fd = 0;    key_t key;    int semid;    struct sembuf sops;    key = ftok("/home/linux/", 1);    semid = semget(key, 1, IPC_CREAT);    fd = open("borad.txt", O_RDWR | O_CREAT | O_APPEND);    sops.sem_num = 0;    sops.sem_op = -1;    semop(semid, &sops, 1);    write(fd, "class math", 11);    sleep(20);    sops.sem_num = 0;    sops.sem_op = +1;    semop(semid, &sops, 1);    close(fd);    return 0;}
运行结果:



0 0