本文共 2715 字,大约阅读时间需要 9 分钟。
信号量通讯的目的有两个:①实现进程互斥②实现进程同步
两个进程对同一资源同时访问有时会造成数据混乱,如进程A,B都要往同一文件写入数据,当进程A写入一部分时,进程B开始写数据,这会导致文件里的数据混乱。使用信号量互斥通讯可以解决这种问题。信号量的实质是一个数字,它标志着进程能否访问资源。信号量的操作主要有获取信号量和释放信号量。使用资源前需要成功获取信号量,使用后需要释放信号量。 信号量(又名信号灯)与其他进程间通信方式不大相同,主要用途是保护临界资源(进程互斥)。进程可以根据它判定是否能够访问某些共享资源。除了用于访问控制外,还可用于进程同步。信号量可分为两类:
1.二值信号灯:信号灯的值只能取0或1 2.计数信号灯:信号灯的值可以取任意非负值。 信号量的编程流程一般为: ①打开信号量,获取一个标示符 ②利用标示符对信号量进行操作 对信号量进行编程涉及到键值的概念。进程要打开一个文件,需要知道该文件的文件名从而找到该文件并打开,而键值类似于文件名。系统的每个ipc对象(信号量,消息队列,共享内存等)在系统中都有一个键值与之对应。不管有没有打开ipc对象,这个键值都是存在的。若要打开一个信号量则必须知道键值。有些文件不存在键值,则可指定它的键值,指定方法有两种: ①任意指定一个数。缺点是若这个数已经被别的IPC对象所使用了,则在与新创建的信号量关联时就会失败。 ②构造一个尽量不会被别的IPC对象用到的数方法:使用key_t ftok( char * fname, int id )原型:int semget(key_t key,int nsems,int semflg)头文件:功能:打开/创建一个信号量集合,成功返回信号量集合标示符(不是获取信号量),失败返回-1参数:key:键值 semflg:可以取值IPC_CREAT,若与key相关联的信号量不存在时会创建一个信号量集合 nsems:创建的这个信号量集合里包含的信号量数目
原型:int semctl(int semid,int semnum,int cmd,.../*union semun arg*/)头文件:功能:根据cmd的值进行相应操作参数:第四个参数是可选的。semid为要操作的信号量集合标示符,semnum为指定要操作的信号量集合里具体的一个信号量,编号从0开始,cmd的取值有10种,其中一种为SETVAL,设置成员semnum的信号量的值,此时第四个参数arg就是要设置的信号量的值。
原型:int semop(int semid,struct sembuf *sops,unsigned nsops)头文件:功能:操作信号量,成功返回0,失败返回-1参数:semid:要操作的信号量集合标示符nsops:要操作多少个信号量struct sembuf结构为:struct sembuf{ unsigned short sem_num; /*指定要操作的信号量集合里具体的一个信号量,编号从0开始*/ short sem_op; /*对信号量的操作,如为-1表示对信号量进行减1操作。只有使结果为非负的操作才能成功操作, 若操作失败则等待直至能操作成功*/ short sem_flg;};
进程A往文件myfile里写数据,写入一部分后停止一段时间,然后接着写:
#include#include #include #include #include #include void main(){ int fd=open("/home/jx/myfile",O_RDWR|O_APPEND,0777); key_t key=ftok("/home/jx/myfile",1); /*创建键值*/ int semid=semget(key,1,IPC_CREAT); /*创建信号量集合,获取标示符*/ semctl(semid,0,SETVAL,1);/*设置信号量初始值*/ /*获取信号量*/ struct sembuf sop; struct sembuf *sops=&sop; sops->sem_num=0; sops->sem_op=-1; sops->sem_flg=SEM_UNDO; semop(semid,sops,1); write(fd,"hello ",6); sleep(10); write(fd,"world!",6); /*释放信号量*/ sops->sem_num=0; sops->sem_op=1; sops->sem_flg=SEM_UNDO; semop(semid,sops,1); close(fd);}
进程B先判断能否往文件myfile里写数据,若不能则等待
#include#include #include #include #include #include void main(){ int fd=open("/home/jx/myfile",O_RDWR|O_APPEND,0777); key_t key=ftok("/home/jx/myfile",1); /*创建键值*/ int semid=semget(key,1,IPC_CREAT); /*创建信号量集合,获取标示符*/ /*获取信号量*/ struct sembuf sop; struct sembuf *sops=&sop; sops->sem_num=0; sops->sem_op=-1; sops->sem_flg=SEM_UNDO; semop(semid,sops,1); write(fd,"this is a program",17); /*释放信号量*/ sops->sem_num=0; sops->sem_op=1; sops->sem_flg=SEM_UNDO; semop(semid,sops,1); close(fd);}
转载地址:http://xmigi.baihongyu.com/