进程 A、B之间利用管道 ,共享内存,信号量来进行通信

时间:2022-02-25 15:10:56


首先先建立两个管道,分别为1—2.fifo  2—1.fifo.建立管道时可以采用mkfifo命令。

在A、B之间通信时可以调用管道进行文件传输。该程序可以简易变为如QQ之间的通信。

该程序所需头文件为

 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/ipc.h>
  4 #include<sys/sem.h>
  5 #include<unistd.h>
  6 #include<errno.h>
  7 #include<string.h>
  8 #include<errno.h>
  9 #include<sys/time.h>
 10 #include<sys/select.h>
 11 #include<fcntl.h>
 12 #include<sys/stat.h>
 13 #include<stdlib.h>
 14 #include<sys/shm.h>

 15 union semun
 16 {
 17     int val;
 18     struct semid_ds *buf;
 19     unsigned short *array;
 20
 21 }arg;
 22 typedef struct shm_num
 23 {
 24     char shm_buf[64];
 25     short shm_show;
 26 }num,*pnum;

初始化信号量和共享内存

进程 A、B之间利用管道 ,共享内存,信号量来进行通信

 pnum init()
 88 {
 89     int semid=semget((key_t)1234,2,IPC_CREAT|0600);
 90     unsigned short arr_buf[2];
 91     int ret;
 92     arr_buf[0]=0;//B传给A的字符串数目
 93     arr_buf[1]=15;//共享内存中的空闲位置数目
 94     arg.array=arr_buf;
 95     ret=semctl(semid,0,SETALL,arg);
 96     if(ret!=0)
 97         perror("semctl");
 98     int shmid=shmget((key_t)1234,1024,IPC_CREAT|0600);//打开共享内存
 99     pnum  p_shm=(pnum)shmat(shmid,NULL,0);//链接共享内存
100     return p_shm;
101 }
</pre><p></p><p>以下为A进程的主函数</p><p><pre name="code" class="cpp"> 30 int main(int argc,char*argv[])
 31 {
 32     int fd1,fd2;
 33     fd1=open("./1-2.fifo",O_WRONLY);
 34     fd2=open("./2-1.fifo",O_RDONLY);//打开A、B之间的管道
 35     if(fd1==-1||fd2==-1)
 36         perror("open");
 37     int ret;
 38     char buf1[64]={0};
 39     char buf2[64]={0};
 40     fd_set readfd;
 41     struct timeval timeout;
 42     pnum pro=init();
 43     int semid=semget((key_t)1234,2,IPC_CREAT|0600);
 44     if(semid==-1)
 45         perror("semget");
 46     int shmid=shmget((key_t)1234,1024,IPC_CREAT|0600);//创建共享内存,大小为1024字节。
 47     if(shmid==-1)
 48         perror("shmid");
 49     while(1)
 50     {
 51         FD_ZERO(&readfd);
 52         FD_SET(STDIN_FILENO,&readfd);
 53         FD_SET(fd2,&readfd);
 54         int maxfd=(STDIN_FILENO>fd2)?STDIN_FILENO+1:fd2+1;
 55         timeout.tv_sec=1;
 56         select(maxfd,&readfd,NULL,NULL,&timeout);//选择该执行的文件运算符

 57         if(FD_ISSET(STDIN_FILENO,&readfd))//从标准输入中读到管道中
 58         {
 59             memset(buf1,0,sizeof(buf1));
 60             ret=read(STDIN_FILENO,buf1,sizeof(buf1));
 61             if(ret<0)
 62                 perror("read");
 63             buf1[strlen(buf1)-1]='\0';
 64             write(fd1,buf1,sizeof(buf1));
 65             shm(pro,buf1,semid);
 66             if(strcmp(buf1,"quit")==0)
 67                 break;
 68         }
 69         if(FD_ISSET(fd2,&readfd))//从管道中读取数据
 70         {
 71             memset(buf2,0,sizeof(buf2));
 72             read(fd2,buf2,sizeof(buf2));
 73             buf2[strlen(buf2)]='\0';
 74             shm(pro,buf2,semid);
 75             if(strcmp(buf2,"quit")==0)
 76                 break;
 77         }
 78     }
 79     sleep(5);
 80     semctl(semid,0,IPC_RMID);
 81     shmdt(NULL);//共享内存段与进程空间分离
 82     shmctl(shmid,IPC_RMID,NULL);//删除共享内存
 83     close(fd1);
 84     close(fd2);
 85     return 0;
 86 }

下边是上述代码中的shm函数,利用信号量,将值写入共享内存

102 void shm(pnum pro,char*buf,int semid)
103 {
104     int ret;
105     struct sembuf sem[2];
106     sem[0].sem_num=0;
107     sem[0].sem_op=1;
108     sem[0].sem_flg=SEM_UNDO;
109     sem[1].sem_num=1;
110     sem[1].sem_op=-1;
111     sem[1].sem_flg=SEM_UNDO;
112     ret=semop(semid,sem,2);//改变信号量的值
113     if(ret!=0)
114         perror("semop");
115     strcpy(pro->shm_buf,buf);//buf写入共享内存
116     pro->shm_show=0;
117     pro++;
118     printf("the buf go to AS is %s\n",buf);
119     printf("the sem0 value is %d\n",semctl(semid,0,GETVAL));
120     printf("the sem1 value is %d\n",semctl(semid,1,GETVAL));
121 }

A进程已经写好了,同样B进程也可用类似的函数写出来,这里就不提出来了。下面是从对应的共享内存中读取数据。同样也用到了上面提到了联合体和头文件,这里就不再叙述了

进程 A、B之间利用管道 ,共享内存,信号量来进行通信

 17 int main(int argc,char argv[])
 18 {
 19     char buf[64]={0};
 20     char * pi=init();
 21     int semid=semget((key_t)1234,2,IPC_CREAT|0600);
 22     if(semid==-1)
 23         perror("open");
 24     int ret;
 25     struct sembuf sem[2];
 26     sem[0].sem_num=0;
 27     sem[0].sem_op=-1;
 28     sem[0].sem_flg=SEM_UNDO;
 29     sem[1].sem_num=1;
 30     sem[1].sem_op=1;
 31     sem[1].sem_flg=SEaM_UNDO;
 32     while(1)
 33     {
 34         memset(buf,0,sizeof(buf));
 35         ret=semop(semid,sem,1);
 36         if(ret!=0)
 37             perror("semid");
 38         strcpy(buf,pi);
 39         printf("the buf from B is %s\n",buf);
 40         *pi=*(pi-64);
 41         ret=semop(semid,sem+1,1);
 42         if(ret!=0)
 43             perror("semid");
 44         printf("the sem0 value is %d\n",semctl(semid,0,GETVAL));
 45         printf("the sem1 value is %d\n",semctl(semid,1,GETVAL));
 46         if(strcmp(buf,"quit")==0)
 47             break;
 48         sleep(5);
 49     }
 50     return 0;
 51 }

同样也可再建立一个BS进程,使之从B的共享内存中读数据。其与A 进程和从A的共享内存中读取数据的AS进程所不同的是,B 的共享内存需选择另一个关键字。