首先先建立两个管道,分别为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;
初始化信号量和共享内存
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进程也可用类似的函数写出来,这里就不提出来了。下面是从对应的共享内存中读取数据。同样也用到了上面提到了联合体和头文件,这里就不再叙述了
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 的共享内存需选择另一个关键字。