Linux操作系统 使用共享内存实现进程通信和同步
共享内存使用
//main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/shm.h>
#include <string.h>
int main()
{int shmid=shmget((key_t)1234,256,IPC_CREAT|0600);assert(shmid!=-1);char *s=(char *)shmat(shmid,NULL,0);// assert(s!=NULL);if(s==(char *)-1){ exit(1);} strcpy(s,"hello");shmdt(s);exit(0);
}//test.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/shm.h>
#include <string.h>
int main()
{int shmid=shmget((key_t)1234,256,IPC_CREAT|0600);assert(shmid!=-1);char *s=(char *)shmat(shmid,NULL,0);// assert(s!=NULL);if(s==(char *)-1){ exit(1);} printf("%s",s);shmdt(s);shmctl(shmid,IPC_RMID,NULL);exit(0);
}
进程a从键盘循环获取数据并拷贝到共享内存中,进程b从共享内存中获取并打印数据。要求a输入一次,b输出一次。a不输入,b也不输出
//main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/shm.h>
#include <string.h>
int main()
{int shmid=shmget((key_t)1234,256,IPC_CREAT|0600);//这里加上IPC_EXCL也可以,去掉也可以assert(shmid!=-1);char *s=(char *)shmat(shmid,NULL,0);// assert(s!=NULL);if(s==(char *)-1){ exit(1);} // strcpy(s,"hello");while(1){printf("input:\n");char buff[128]={0};fgets(buff,128,stdin);strcpy(s,buff);if(strncmp(buff,"end",3)==0){ break;} }shmdt(s);exit(0);
}//test.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/shm.h>
#include <string.h>
int main()
{int shmid=shmget((key_t)1234,256,IPC_CREAT|0600);assert(shmid!=-1);char *s=(char *)shmat(shmid,NULL,0);// assert(s!=NULL);if(s==(char *)-1){ exit(1);} // printf("%s",s);while(1){if(strncmp(s,"end",3)==0){ break;} printf("read:%s\n",s);sleep(1);}shmdt(s);shmctl(shmid,IPC_RMID,NULL);exit(0);
}
上面代码会出现问题,会发现如果不sleep(1),他就会一直打印下去。所以共享内存,必须结合信号量一起使用
//sem.h
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#define SEM1 0
#define SEM2 1
#define SEM_MAX 2
union semun
{int val;
};void sem_init();
void sem_p(int index);
void sem_v(int index);
void sem_destroy();//sem.c
#include "sem.h"
static int semid=-1;
void sem_init()
{semid=semget((key_t)1234,SEM_MAX,IPC_CREAT|IPC_EXCL|0600);if(semid==-1){semid=semget((key_t)1234,SEM_MAX,0600);if(semid==-1){printf("sem failed!\n");return ;}}else{union semun a;int arr[SEM_MAX]={1,0};for(int i=0;i<SEM_MAX;i++){a.val=arr[i];if(semctl(semid,i,SETVAL,a)==-1){printf("semctl setval failed\n");}}}
}void sem_p(int index)
{if(index<0||index>=SEM_MAX){return ;}struct sembuf a;a.sem_num=index;a.sem_op=-1;a.sem_flg=SEM_UNDO;if(semop(semid,&a,1)==-1){printf("semop p error!\n");}
}
void sem_v(int index)
{if(index<0||index>=SEM_MAX){return ;}struct sembuf a;a.sem_num=index;a.sem_op=1;a.sem_flg=SEM_UNDO;if(semop(semid,&a,1)==-1){printf("semop v error!\n");}
}void sem_destroy()
{if(semctl(semid,0,IPC_RMID)==-1){printf("destroy error!\n");}
}//main.c
#include <string.h>
#include "sem.h"
#include <sys/shm.h>int main()
{int shmid=shmget((key_t)1234,256,IPC_CREAT|0600);assert(shmid!=-1);char *s=(char *)shmat(shmid,NULL,0);// assert(s!=NULL);if(s==(char *)-1){ exit(1);} // strcpy(s,"hello");char buff[128];sem_init();while(1){printf("input:\n");memset(buff,128,0);fgets(buff,128,stdin);sem_p(SEM1);strcpy(s,buff);sem_v(SEM2);if(strncmp(buff,"end",3)==0){ break;} }shmdt(s);exit(0);
}//b.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/shm.h>
#include <string.h>
#include "sem.h"
int main()
{int shmid=shmget((key_t)1234,256,IPC_CREAT|0600);assert(shmid!=-1);char *s=(char *)shmat(shmid,NULL,0);// assert(s!=NULL);if(s==(char *)-1){ exit(1);} // printf("%s",s);sem_init();while(1){sem_p(SEM2);if(strncmp(s,"end",3)==0){ break;} printf("read:%s\n",s);sem_v(SEM1);}shmdt(s);sem_destroy();shmctl(shmid,IPC_RMID,NULL);exit(0);
}