进程间通信(3)--信号量

           信号量与简单互斥锁的实现

信号量:与管道和消息队列不同,信号量可以说是一个计数器,它用来控制多进程对临界资源的访问,它作的是PV操作,P为减一操作,它是用来获取临界资源的使用权,如果减一之后大于零则可以访问,不然就挂起等待,V为加一操作,当进程对他的访问结束后便执行,用来归还资源的使用权。

原子操作:PV的加一减一都是原子操作也就是说加一减一对应的计算机语言只有一条操作,如果不这样设计就会引起双方同时的申请导致不能正常执行。

int semget(key_t key, int nsems, int semflg);
这是信号量的获取函数,nsmes表示要申请的信号量集的个数,另外两个都很熟悉了。
The semid_ds data structure is defined in <sys/sem.h> as follows:

           struct semid_ds {
               struct ipc_perm sem_perm;  /* Ownership and permissions */
               time_t          sem_otime; /* Last semop time */
               time_t          sem_ctime; /* Last change time */
               unsigned short  sem_nsems; /* No. of semaphores in set */
           };
 上面是计算机内核为每个信号量集设计的一个结构体。每个信号量
 
  int semop(int semid, struct sembuf *sops, unsigned nsops);
  这个函数就是用来执行PV操作的函数,
           struct sembuf{
           unsigned short sem_num;  /* semaphore number */
           short          sem_op;   /* semaphore operation */
           short          sem_flg;  /* operation flags */
           };//这个结构体是用来操作每一个信号所使用的一个结构,sem_num表示
           要操作的是第几个信号(数组下标),sem_op表示执行PV操作中的哪一种。

*sem_flg();它是semop中sembuf结构体的一个对象,它的作用是用来选择一种执行方式的

有0阻塞式等待,IPC_NOWAIT(非阻塞式等待),SEM_UNDO(如它的名字一样什么也不做,在这个进程执行的所有PV操作在这个进程结束后信号量的值都还原为刚进入这个进程时的值,避免此进程出错)



        信号量实现一个互斥锁的代码

对比可以看出由于进程间的互斥访问输出,没有ab的交错

comm.c

  1 #include"comm.h"
  2 union semun {
  3     int  val;    /* Value for SETVAL */
  4     struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
  5     unsigned short  *array;  /* Array for GETALL, SETALL */
  6     struct seminfo  *__buf;  /* Buffer for IPC_INFO*/
  7 };
  8 
  9 static int comm_get_sem(int msems,int flag)
 10 {
 11     key_t _sem_key=ftok(_PATH_,_PROJ_ID);
 12     if(_sem_key<0)
 13     {
 14         perror("ftok");
 15         return -1;
 16     }
 17     int sem_id=semget(_sem_key,msems,flag);
 18     if(sem_id<0)
 19     {
 20         return -1;
 21     }
 22     return sem_id;
 23 
 24 }
 25 int creat_sem(int nsems)
 26 {
 27     umask(0);
 28     return comm_get_sem(nsems,IPC_CREAT|IPC_EXCL|0666);
 29 }
 30 
 31 int get_sem()
 32 {
 33     return comm_get_sem(0,IPC_CREAT);
 34 }
 35 int init_sem(int semid,int whitch)
 36 {
 37     union semun _semnu;
 38     _semnu.val=1;
 39     int ret = semctl(semid,whitch,SETVAL,_semnu);
 40     return ret;
 41 }
 42 static int sem_op(int semid,struct sembuf *sops,unsigned nsops)
 43 {
 44         return semop(semid,sops,nsops);
 45 }
 46 int p_sem_op(int semid,int which)
 47 {
 48     struct  sembuf sem;
 49     sem.sem_op=-1;
 50     sem.sem_num=which;
 51     sem.sem_flg=SEM_UNDO;
 52     return sem_op(semid,&sem,1);
 53 }
 54 
 55 int v_sem_op(int semid,int which)
 56 {
 57     struct sembuf sem;
 58     sem.sem_op=1;
 59     sem.sem_num=which;
 60     sem.sem_flg=SEM_UNDO;
 61     return sem_op(semid,&sem,1);
 62 }
 63 int destroy_sem(int sem_id)
 64 {
 65     int ret =semctl(sem_id,0,IPC_RMID,NULL);
 66 
 67     if(ret <0){
 68             return -1;
 69         }
 70     return 0;
 71 }

sem_socket.c

  1 #include"comm.h"
  2 
  3 int main()
  4 {
  5     int sem_id=creat_sem(1);
  6     int ret=init_sem(sem_id,0);
  7     pid_t id=fork();
  8     if(id<0)
  9     {
 10         perror("fork");
 11     }else if(id==0){
 12             int sem_id=get_sem();
 13             while(1){
 14         //          printf("child begin:\n");
 15         p_sem_op(sem_id,0);
 16         printf("A");
 17         fflush(stdout);
 18         sleep(2);
 19         printf("A");
 20         fflush(stdout);
 21         sleep(1);
 22         v_sem_op(sem_id,0);
 23         }
 24     }else{
 25         while(1)
 26             {
 27             //sleep(10);
 28             p_sem_op(sem_id,0);
 29             printf("B");
 30             fflush(stdout);
 31             sleep(1);
 32             printf("B");
 33             fflush(stdout);
 34             sleep(2);
 35             v_sem_op(sem_id,0);
 36         }
 37         waitpid(id,0,NULL);
 38     }
 39 
 40 
 41     return 0;
 42 }
"sem_socket.c" 42L, 588C                                                                      1,1          顶端
时间: 2024-10-16 18:13:48

进程间通信(3)--信号量的相关文章

VxWorks进程间通信2 -- 信号量

VxWorks进程间通信2 -- 信号量一.信号量的概念 是实现任务互斥.同步操作的主要机制.VxWorks提供的信号量经过了高度优化,在所有任务间通信机制中,速度最快. 二.信号量的分类 Binary Semaphores(二进制):完成互斥.同步操作的最佳方式:速度最快,最常用. Mutual Exclusion Semaphores(互斥):一种特殊的二进制信号量,专门针对互斥操作进行了优化. Counting Semaphores(计数):类似于二进制信号量,可记录信号量释放的次数,可监

Linux进程间通信:信号量

上次书写了进程间通信的消息队列,这次是IPC中的另一个模块.信号量 信号量是什么? 荷兰计算机科学家Dijkstra把互斥的关键含义抽象称为信号量(semaphore)概念.信号量是一个被保护的量. 信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的 通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识.信号 量在此过程中负责数据操作的互斥.同步等功能. 当请求一个使用信号量来表示的资源时,进程需要先读取信号量的值来判断资源是否可 用.大于0,资源可

在Linxu下进程间通信之信号量

(一) 信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识.信号量在此过程中负责数据操作的互斥.同步等功能. 当请求一个使用信号量来表示的资源时,进程需要先读取信号量的值来判断资源是否可用.当信号量的值大于0时,资源可以请求,等于0,无资源可用,进程会进入睡眠状态直到资源可用.当进程不再使用一个信号量控制的共享资源时,信号量的值+1,对信号量的值进行的增减操作均为原子操作,这是由于信号量主要的作用是

进程间通信之信号量

一.对信号量的理解 信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识. 当请求一个使用信号量来表示的资源时,进程需要先读取信号量的值来判断资源是否可用.大于0,资源可以请求,小于0,无资源可用,进程会进入睡眠状态直至资源可用.当进程不再使用一个信号量控制的共享资源时,信号量的值+1,对信号量的值进行的增减操作均为原子操作. 二.使用信号量的原因 防止出现因多个程序同时访问一个共享资源时而引发的一系

进程间通信之-----信号量

进程间通信简单的说有三个问题,第一个问题是:一个进程如何把信息传递给另一个,第二个问题是:要确保两个或者更多的进程在互动中不会出现交叉(即是进程互斥问题),第三个问题是:进程间同步问题. 四种进程或者线程同步互斥的控制方法 1):临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问. 2):互斥量:为协调共同对一个共享资源的单独访问而设计的 3):信号量:为控制一个具有有限数量用户资源而设计 4):事件:用来通知线程有一些事件已发生,从而启动后继任务的开始. 临界区(C

Linux进程间通信——使用信号量(转)

这篇文章将讲述别一种进程间通信的机制--信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信--使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同

Linux进程间通信——使用信号量【转】

本文转载自:http://blog.csdn.net/ljianhui/article/details/10243617 这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信——使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线

Linux进程间通信--使用信号量【转】

本文转载自:http://blog.csdn.net/ljianhui/article/details/10243617 这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信——使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线

Linux进程间通信——使用信号量

这篇文章将讲述别一种进程间通信的机制--信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信--使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同

Linux进程间通信:管道,信号量,消息队列,信号,共享内存,套接字

Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间的通信方面的侧重点有所不同.前者是对UNIX早期的进程间通信手段进行了系统的改进和扩充,形成了“system V IPC”,其通信进程主要局限在单个计算机内:后者则跳过了该限制,形成了基于套接口(socket)的进程间通信机制.而Linux则把两者的优势都继承了下来 linux进程间通信(IPC)有几种方式