linux进程同步与通信(共享内存和信号量)

来源:互联网 发布:枪林弹雨刷金币软件 编辑:程序博客网 时间:2024/05/16 10:31

1)  设计编写以下程序,着重考虑其同步问题:

a)        一个程序(进程)从客户端读入按键信息,一次将“一整行”按键信息保存到一个共享存储的缓冲区内并等待读取进程将数据读走,不断重复上面的操作;

b)       另一个程序(进程)生成两个进程,用于显示缓冲区内的信息,这两个进程并发读取缓冲区信息后将缓冲区清空(一个进程的两次显示操作之间可以加入适当的时延以便于观察)。

c)        在两个独立的终端窗口上分别运行上述两个程序,展示其同步与通信功能,要求一次只有一个任务在操作缓冲区。

d)       运行程序,记录操作过程的截屏并给出文字说名。

要求使用posix信号量来完成这里的生产者和消费者的同步关系。







//头文件shm_com_sem.h#include <fcntl.h> #include <sys/stat.h>#include <semaphore.h>  #define LINE_SIZE 256#define NUM_LINE 16const char * queue_mutex="queue_mutex";const char * queue_empty="queue_empty";const char * queue_full="queue_full";//公用缓冲区  struct shared_mem_st{char buffer[NUM_LINE][LINE_SIZE];//缓冲数据组int line_write;//读写指针int line_read;};//producer.c#include <stdio.h>  #include <sys/ipc.h>  #include <sys/shm.h>  #include <semaphore.h>  #include <fcntl.h>  #include <stdlib.h>  #include <unistd.h>  #include <string.h>#include "shm_com_sem.h"int main(void){void *shared_memory=(void *)0;//共享内存 缓冲区指针struct shared_mem_st *shared_stuff;char key_line[256];int stmid;//共享内存idsem_t *sem_queue,*sem_queue_empty,*sem_queue_full;//访问共享内存的信号量指针stmid=shmget((key_t)1234,sizeof(struct shared_mem_st),0666|IPC_CREAT);//创建一个新的共享内存 if(stmid==-1)    {      perror("shmget failed");      exit(1);    }if((shared_memory = shmat(stmid,0,0))<(void *)0){  //若共享内存区映射到本进程的进程空间失败        perror("shmat failed");          exit(1);      } shared_stuff=(struct shared_mem_st *)shared_memory;//将缓冲区指针转换为shared_mem_st格式sem_queue=sem_open("queue_mutex",O_CREAT,0644,1);sem_queue_empty=sem_open("queue_empty",O_CREAT,0644,1);sem_queue_full=sem_open("queue_full",O_CREAT,0644,1);//创建三个信号量//读写指针初始化shared_stuff->line_write=0;shared_stuff->line_read=0;char b[BUFSIZ];int running=1;while(running){sleep(1);sem_wait(sem_queue_empty);sem_wait(sem_queue);//等待信号量输入printf("Enter some text:");fgets(b,BUFSIZ,stdin);strncpy(shared_stuff->buffer[shared_stuff->line_write],b,LINE_SIZE);shared_stuff->line_write=(shared_stuff->line_write+1)%NUM_LINE;//写指针增加if(strncmp(b,"end",3)==0)//如果输入为end则退出{ running=0; }sem_post(sem_queue);//发送信号量sem_post(sem_queue_full);}//为了防止结束后进程阻塞,所以再发送一次信号量和内容sem_post(sem_queue);//发送信号量sem_post(sem_queue_full);strncpy(shared_stuff->buffer[shared_stuff->line_write],b,LINE_SIZE);shared_stuff->line_write=(shared_stuff->line_write+1)%NUM_LINE;//写指针增加if(shmdt(shared_memory)==-1)//解除映射{fprintf(stderr,"shmdt failed\n");exit(EXIT_FAILURE);}//删除共享内存区if(shmctl(stmid,IPC_RMID,0)==-1){fprintf(stderr,"shmctl failed\n");exit(EXIT_FAILURE);}}//customer.c#include <stdio.h>  #include <sys/ipc.h>  #include <sys/shm.h>  #include <semaphore.h>  #include <fcntl.h>  #include <stdlib.h>  #include <unistd.h>  #include <string.h>#include "shm_com_sem.h"int main(void){void * shared_memory=(void *)0;struct shared_mem_st *shared_stuff;int stmid;int num_read;pid_t fork_result;sem_t *sem_queue,*sem_queue_empty,*sem_queue_full;stmid=shmget((key_t)1234,sizeof(struct shared_mem_st),0666|IPC_CREAT);//获得已创建共享内存 if(stmid==-1)    {      perror("shmget failed");      exit(1);    }if((shared_memory = shmat(stmid,0,0))<(void *)0){  //若共享内存区映射到本进程的进程空间失败        perror("shmat failed");          exit(1);      } shared_stuff=(struct shared_mem_st *)shared_memory;//获取三个信号量sem_queue=sem_open("queue_mutex",0);sem_queue_empty=sem_open("queue_empty",0);sem_queue_full=sem_open("queue_full",0);//创建两个进程fork_result=fork();if(fork_result==-1)fprintf(stderr,"fork failed\n");int running=1;if(fork_result==0)//子进程{while(running){sem_wait(sem_queue_full);sem_wait(sem_queue);//等待信号量sleep(2);printf("child pid is %d,you wrote:%s\n",getpid(),shared_stuff->buffer[shared_stuff->line_read]);//输出进程号和消息内容if(strncmp(shared_stuff->buffer[shared_stuff->line_read],"end",3)==0)//如果为end则退出{running=0;}//printf("%d",running);shared_stuff->line_read=(shared_stuff->line_read+1)%NUM_LINE;//读指针改变sem_post(sem_queue);//发送信号量sem_post(sem_queue_empty);}sem_unlink(queue_mutex);sem_unlink(queue_empty);sem_unlink(queue_full);}else//父进程{while(running){    sem_wait(sem_queue_full);sem_wait(sem_queue);//等待信号量sleep(2);printf("parent pid is %d,you wrote:%s\n",getpid(),shared_stuff->buffer[shared_stuff->line_read]);//输出进程号和消息内容if(strncmp(shared_stuff->buffer[shared_stuff->line_read],"end",3)==0)//如果为end则退出{ running=0;}//printf("%d",running);shared_stuff->line_read=(shared_stuff->line_read+1)%NUM_LINE;//读指针改变sem_post(sem_queue);//发送信号量sem_post(sem_queue_empty);}   sem_unlink(queue_mutex);sem_unlink(queue_empty);sem_unlink(queue_full);}waitpid(fork_result,NULL,0);exit(EXIT_SUCCESS);}


0 0