信号量实现进程同步

 
  1. #include<sys/mman.h>    
  2. #include<sys/types.h>    
  3. #include<linux/sem.h>    
  4. #include<fcntl.h>    
  5. #include<unistd.h>    
  6. #include<stdio.h>    
  7. #include<errno.h>    
  8. #include<time.h>    
  9. #define MAXSEM 5    /*声明三个信号量ID*/     
  10. int fullid;     
  11. int emptyid;     
  12. int mutxid;        
  13. int main(){     
  14.     struct sembuf P,V;     
  15.     union semun arg;   /* 声明共享主存*/     
  16.     int *array;     
  17.     int *sum;     
  18.     int *set;     
  19.     int *get;   /*将array、sum、set、get映射到共享主存*/     
  20.     array=(int *)shmat(shmget(IPC_PRIVATE,sizeof(int)*MAXSEM,IPC_CREAT|0666),0,0);     
  21.     sum=(int *)shmat(shmget(IPC_PRIVATE,sizeof(int),IPC_CREAT|0666),0,0);     
  22.     set=(int *)shmat(shmget(IPC_PRIVATE,sizeof(int),IPC_CREAT|0666),0,0);     
  23.     get=(int *)shmat(shmget(IPC_PRIVATE,sizeof(int),IPC_CREAT|0666),0,0);     
  24.     *get=0;   /*创建信号量fullid、emptyid和mutxid*/     
  25.       
  26.     fullid=semget(IPC_PRIVATE,0666|IPC_CREAT);     
  27.     emptyid=semget(IPC_PRIVATE,0666|IPC_CREAT);     
  28.     mutxid=semget(IPC_PRIVATE,0666|IPC_CREAT);      /*为信号量赋值*/     
  29.     arg.val=0;     
  30.     if(semctl(fullid,0,SETVAL,arg)==-1)   
  31.         perror("semctl setval error");     
  32.     arg.val=MAXSEM;     
  33.     if(semctl(emptyid,0,SETVAL,arg)==-1)   
  34.         perror("semctl setval error");     
  35.     arg.val=1;     
  36.     if(semctl(mutxid,0,SETVAL,arg)==-1)   
  37.         perror("semctl setval error");      /*初始化PV*/     
  38.     P.sem_num=0;     
  39.     P.sem_op=-1;     
  40.     P.sem_flg=SEM_UNDO;     
  41.     V.sem_num=0;     
  42.     V.sem_op=1;     
  43.     V.sem_flg=SEM_UNDO;      /*创建生产者进程*/     
  44.     if(fork()==0){      
  45.         int i=0;      
  46.         *set=0;      
  47.         while(i<100){       
  48.             semop(emptyid,&P,1);       
  49.             semop(mutxid,&P,1);//对emptyid、mutxid执行P操作            
  50.             array[(*set)%MAXSEM]=i+1;       
  51.             (*set)++;            
  52.             semop(mutxid,&V,1);         //对emptyid、mutxid执行V操作                
  53.             semop(fullid,&V,1);          //       
  54.             i++;    }      
  55.         sleep(3);      
  56.         printf("生产者结束\n");      
  57.         exit(0);      
  58.     }else{     /*创建消费者进程*/       
  59.         if(fork()==0){      while(1){         
  60.             semop(fullid,&P,1);        //对emptyid、mutxid执行P操作         
  61.             semop(mutxid,&P,1);       //           
  62.             if(*get==100)         
  63.                 break;         
  64.             *sum+=array[(*get)%MAXSEM];         
  65.             printf("The ConmsumerA Get Number %d\n",array[(*get)%MAXSEM]);         
  66.             (*get)++;         
  67.             if(get==100)         
  68.                 printf("The sum is %d\n",sum);         
  69.             semop(mutxid,&V,1);         
  70.             semop(emptyid,&V,1);         
  71.             sleep(1);             }        
  72.         printf("消费者结束\n");        
  73.         exit(0);      }else{     /*创建消费者进程B*/       
  74.             if(fork()==0){        
  75.                 while(1){         
  76.                     semop(fullid,&P,1);        //对emptyid、mutxid执行P操作         
  77.                     semop(mutxid,&P,1);               
  78.                     if(*get==100)            
  79.                         break;         
  80.                     *sum+=array[(*get)%MAXSEM];         
  81.                     printf("The ConmsumerB Get Number %d\n",array[(*get)%MAXSEM]);         
  82.                     (*get)++;         
  83.                     if(get==100)         
  84.                         printf("The sum is %d\n",sum);         
  85.                     semop(mutxid,&V,1);         
  86.                     semop(emptyid,&V,1);         
  87.                     sleep(1);             }        
  88.                 printf("消费者B结束!\n");        
  89.                 exit(0);      
  90.             }         
  91.         }     
  92.     }     
  93. }  

 

本文出自 “阿凡达” 博客,请务必保留此出处http://shamrock.blog.51cto.com/2079212/724992

### 使用信号量实现进程同步的操作系统原理 在多道程序环境中,多个进程可能需要访问共享资源。为了防止这些进程同时修改同一数据而导致不一致的结果,操作系统引入了信号量这一抽象机制[^1]。 #### 什么是信号量信号量是一种特殊的变量,用于管理对临界区(Critical Section)——即一段不允许两个或更多进程并发执行的代码区域——的访问权限。信号量可以分为两种类型: - **二进制信号量**:仅取0或1值,表示资源是否可用; - **计数信号量**:可取任意非负整数值,代表可供分配给不同进程使用的同类资源数量。 #### P操作与V操作 对于任何类型的信号量S而言,都定义了两种基本操作P(S)和V(S),也称为wait()和signal(): - `P(S)` (Proberen/测试): 如果S>0,则减去1;如果S=0,则阻塞调用此函数的进程直到其他某个进程执行`V(S)` - `V(S)` (Verhogen/增加): 将S加1,并唤醒因等待该信号量而被挂起的一个进程(如果有) 这两种原语必须原子地完成其工作,这意味着它们要么全部被执行,要么完全未被执行,在其间不应发生中断事件。 #### 实现示例 下面是一个简单的Python模拟例子,展示了如何利用信号量解决生产者消费者问题: ```python import threading from time import sleep import random buffer = [] mutex = threading.Semaphore(1) empty = threading.Semaphore(10) # 假设缓冲区大小为10 full = threading.Semaphore(0) def producer(): while True: item = 'item-' + str(random.randint(1, 99)) empty.acquire() mutex.acquire() buffer.append(item) print(f'Produced {item}, Buffer size={len(buffer)}') mutex.release() full.release() sleep_time = random.uniform(0.5, 1.5) sleep(sleep_time) def consumer(): while True: full.acquire() mutex.acquire() item = buffer.pop(0) print(f'Consumed {item}, Buffer size={len(buffer)}') mutex.release() empty.release() sleep_time = random.uniform(0.5, 1.5) sleep(sleep_time) if __name__ == '__main__': t1 = threading.Thread(target=producer) t2 = threading.Thread(target=consumer) t1.start() t2.start() t1.join() t2.join() ``` 在这个例子中,`empty`, `full` 和 `mutex` 都是信号量对象。`empty` 表示还有多少空间可用于存储新项目;`full` 显示当前有多少项已经准备好供消费;`mutex` 则用来保护对共享列表 `buffer` 的访问,确保每次只有一个线程能够更改这个列表的内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值