IO进程:信号灯集

文章详细介绍了使用C语言实现的信号灯(Semaphore)相关函数,包括创建、初始化、申请/释放资源、删除信号灯集,以及共享内存的创建、映射和操作。
摘要由CSDN通过智能技术生成

程序代码:

sem.h:

  1 #ifndef __SEM_H__
  2 #define __SEM_H__
  3 
  4 //创建信号灯集并初始化,semcount表示灯个数
  5 int open_sem(int semcount);
  6 
  7 //申请资源操作,semno表示灯的编号
  8 int P(int semid,int semno);
  9 
 10 //释放资源操作,semno表示灯的编号
 11 int V(int semid,int semno);
 12 
 13 //删除信号灯集
 14 int del_sem(int semid);
 15 
 16 #endif                                                                                            
~             

sem.c:

  1 #include<myhead.h>
  2 union semun
  3 {
  4     int val;
  5     struct semid_ds *buf;
  6     unsigned short *array;
  7     struct seminfo *__buf;
  8 };
  9 //定义给信号灯集中的指定信号灯赋值
 10 int init_semno(int semid,int semno)
 11 {
 12     union semun buf;
 13     printf("请输入要给编号为%d的灯设置的值:",semno);
 14     scanf("%d",&buf.val);
 15     //调用控制函数
 16     if(semctl(semid,semno,SETVAL,buf)==-1)
 17     {
 18         perror("semctl error");
 19         return -1;
 20     }
 21     return 0;
 22 }
 23 //创建或打开共享内存,参数为要申请的信号灯集中包含的灯的个数,返回值信号灯集的id
 24 int open_sem(int semcount)
 25 {
 26     //创建key值
 27     key_t key=-1;
 28     if((key=ftok("/",'s'))==-1)
 29     {
 30         perror("ftok error");
 31         return -1;
 32     }
 33     //通过key值创建一个信号灯集
 34     int semid=-1;
 35     if((semid=semget(key,semcount,IPC_CREAT|IPC_EXCL|0664))==-1)
 36     {
 37         //对错误码判断,EEXIST,说明信号灯集已存在
 38         if(errno==EEXIST)
 39         {
 40             //直接打开信号灯集即可
 41             semid=semget(key,semcount,IPC_CREAT|0664);
 42             return semid;
 43         }
 44         perror("semget error");
 45         return -1;
 46     }
 47     //给信号灯集的每个灯进行初始化操作
 48     for(int i=0;i<semcount;i++)
 49     {
 50         //对编号为i的灯进行初始化
 51         init_semno(semid,i);
 52     }
 53     return semid;
 54 }
 55 //进行申请资源操作,参数要申请的信号灯id,以及灯的编号
 56 int P(int semid,int semno)
 57 {
 58     //定义要执行操作的结构体变量
 59     struct sembuf buf;
 60     buf.sem_num=semno;
 61     buf.sem_op=-1;//申请资源
 62     buf.sem_flg=0;//阻塞方式申请
 63     //执行函数
 64     if(semop(semid,&buf,1)==-1)
 65     {
 66         perror("P error");
 67         return -1;
 68     }
 69     return 0;
 70 }
 71 //进行释放资源操作,参数为要申请的信号灯id,以及灯的编号
 72 int V(int semid,int semno)
 73 {
 74     struct sembuf buf;
 75     buf.sem_num=semno;
 76     buf.sem_op=1;
 77     buf.sem_flg=0;
 78     if(semop(semid,&buf,1)==-1)
 79     {
 80         perror("V error");
 81         return -1;
 82     }
 83     return 0;
 84 }
 85 //删除信号灯集的操作,参数为要删除的信号灯集
 86 int del_sem(int semid)
 87 {
 88     //删除信号灯集
 89     if(semctl(semid,0,IPC_RMID)==-1)                                                                                                                                                                                                                                         
 90     {
 91         perror("delete error");
 92         return -1;
 93     }
 94     return 0;
 95 }
~              

shmsnd.c:

  1 #include<myhead.h>
  2 #include "1.h"
  3 #define PAGE_SIZE 4096
  4 int main(int argc, const char *argv[])
  5 {
  6     //11.创建并初始化一个信号灯集
  7     int semid=open_sem(2);
  8     //1.创建key值
  9     key_t key=-1;
 10     if((key=ftok("/",'k'))==-1)
 11     {
 12         perror("ftok error");
 13         return -1;
 14     }
 15     printf("key=%d\n",key);
 16     //2.将物理内存创建出共享内存段
 17     int shmid=-1;
 18     if((shmid=shmget(key,PAGE_SIZE,IPC_CREAT|0664))==-1)
 19     {
 20         perror("shmget error");
 21         return -1;
 22     }
 23     printf("shmid=%d\n",shmid);
 24     //3.将共享内存段地址映射到用户空间
 25     //NULL表示让系统自动选择页的分段
 26     //0表示当前进程对共享内存具有读写功能
 27     char *addr=(char *)shmat(shmid,NULL,0);
 28     if(addr==(void*)-1)
 29     {
 30         perror("shmat error");
 31         return -1;
 32     }
 33     printf("addr=%p\n",addr);
 34     //4.操作共享内存
 35     //char buf[128]="";
 36     while(1)
 37     {
 38         //22.申请0号灯的资源
 39         P(semid,0);
 40         printf("请输入>>>");
 41         fgets(addr,PAGE_SIZE,stdin);//从终端输入数据
 42         addr[strlen(addr)-1]='\0';//将换行换成'\0'
 43         printf("发送成功\n");
 44         //33.释放1号灯的资源
 45         V(semid,1);
 46         if(strcmp(addr,"quit")==0)
 47             break;
 48     }
 49     //5.取消映射
 50     if(shmdt(addr)==-1)
 51     {
 52         perror("shmdt error");
 53         return -1;
 54     }
 55     //6.删除共享内存
 56     if(shmctl(shmid,IPC_RMID,NULL)==-1)
 57     {
 58         perror("shmctl error");
 59         return -1;
 60     }
 61     return 0;
 62 }                                                                                                                                                                                                       
~          

 shmrcv:

  1 #include<myhead.h>
  2 #include"1.h"
  3 #define PAGE_SIZE 4096
  4 int main(int argc, const char *argv[])
  5 {
  6     //11.创建信号灯集
  7     int semid=open_sem(2);
  8     //1.创建key值
  9     key_t key=-1;
 10     if((key=ftok("/",'k'))==-1)
 11     {
 12         perror("ftok error");
 13         return -1;
 14     }
 15     printf("key=%d\n",key);
 16     //2.将物理内存创建共享内存段
 17     int shmid=-1;
 18     if((shmid=shmget(key,PAGE_SIZE,IPC_CREAT|0664))==-1)
 19     {
 20         perror("shmget error");
 21         return -1;
 22     }
 23     printf("shmid=%d\n",shmid);
 24     //3.将共享内存段地址映射到用户空间
 25     //NULL表示让系统自动选择页分段
 26     //0表示当前进程对共享内存的读写功能
 27     char *addr=(char*)shmat(shmid,NULL,0);
 28     if(addr==(void*)-1)
 29     {
 30         perror("shmat error");
 31         return -1;
 32     }
 33     printf("addr=%p\n",addr);
 34     //4.操作共享内存
 35     //char buf[128]="";                                                                                                             
 36     while(1)
 37     {
 38         //22.申请1号灯的资源
 39         P(semid,1);
 40         printf("共享内存中的数据为:%s\n",addr);
 41         if(strcmp(addr,"quit")==0)
 42             break;
 43         //33.释放0号灯的资源
 44         V(semid,0);
 45     }
 46     //5.取消映射
 47     if(shmdt(addr)==-1)
 48     {
 49         perror("shmdt error");
 50         return -1;
 51     }
 52     //44.删除信号灯集
 53     del_sem(semid);
 54     return 0;
 55 }
~          

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值