实验名称:Linux进程间通信
所有的文件 和 报告 在 :https://github.com/menghuanali/Linux7
实验目的及要求
学习和掌握Linux信号概念,并能使用系统调用完成电子表计时程序。
学习和掌握Linux进程间通信的IPC方法。
学习和掌握利用信号量实现进程间的同步通信。
二、实验内容
所有文件汇总
Linux信号
输入程序7-1,7-2编译并运行写出执行结果。
7-1结果
7-2结果
可以看到,第一次按下终止命令(ctrl+c)时,进程并没有被终止,面是输出OUCH! - I got signal 2,因为SIGINT的默认行为被signal函数改变了,当进程接受到信号SIGINT时,它就去调用函数ouch去处理,注意ouch函数把信号SIGINT的处理方式改变成默认的方式,所以当你再按一次ctrl+c时,进程就像之前那样被终止了。
对比执行结果,你得到的启示是:
区别在于,7_2中ouch函数中又进行安装信号函数。即当ouch函数捕获外部中断的SGIINT信号后,改变安装信号函数(接受中断信号,进程结束)利用Linux信号SIGALAM,设计并实现电子表程序。
IPC方法—管道
输入程序7-3,编译并运行写出执行结果。
双向管道实现聊天室功能!
IPC方法—命名管道(FIFO)
输入程序7-4,7-5编译并运行写出执行结果。
本程序是一个使用FIFO(命名管道)进行进程间通信的典型程序
lucy.c创建了FIFO write_fifo用于向程序peter.c发送信息;
peter.c程序创建了FIFO read-fifo,用于向lucy.c发送消息。
先运行peter.c 再运行lucy.c
IPC方法—信号量
输入程序7-6 semun.h和7-7 sem1.c,编译执行并写出结果。
输入程序7-8和7-9,编译执行并写出结果。
创建 shares-file文件,实现双方通信文件里乱码
程序7-8和7-9中哪段代码实现了共享,描述实现内存映射的主要函数的参数意义
fd = open(filenm, O_RDWR | O_CREAT);
mmap_addr = (char*)mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
mmap函数中,0表示有系统分配映射内存的地址;4096表示映射内存大小为4096B ,
IPC方法—共享内存
输入程序7-10和7-11,编译执行并写出结果。
简述程序7-10和7-11,是否实现了共享内存互斥访问,如何实现?
实现了共享实现了内存互斥访问,利用结构体中的变量wrritten_by_you。1为读,0为写
du.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"
int main(void)
{
int running=1;
void *shared_memory=(void *)0;
struct shared_use_st *shared_stuff;
int shmid;
/*创建共享内存*/
shmid=shmget((key_t)1234,sizeof(structshared_use_st),0666|IPC_CREAT);
if(shmid==-1)
{
fprintf(stderr,"shmget failed\n");
exit(EXIT_FAILURE);
}
/*映射共享内存*/
shared_memory=shmat(shmid,(void *)0,0);
if(shared_memory==(void *)-1)
{
fprintf(stderr,"shmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at%X\n",(int)shared_memory);
/*让结构体指针指向这块共享内存*/
shared_stuff=(struct shared_use_st*)shared_memory;
/*控制读写顺序*/
shared_stuff->written_by_you=0;
/*循环的从共享内存中读数据,直到读到“end”为止*/
while(running)
{
if(shared_stuff->written_by_you)
{
printf("You wrote:%s",shared_stuff->some_text);
sleep(1); //读进程睡一秒,同时会导致写进程睡一秒,这样做到读了之后再写
shared_stuff->written_by_you=0;
if(strncmp(shared_stuff->some_text,"end",3)==0)
{
running=0; //结束循环
}
}
}
/*删除共享内存*/
if(shmdt(shared_memory)==-1)
{
fprintf(stderr,"shmdt failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
xie.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"
int main(void)
{
int running=1;
void *shared_memory=(void *)0;
struct shared_use_st *shared_stuff;
char buffer[BUFSIZ];
int shmid;
/*创建共享内存*/
shmid=shmget((key_t)1234,sizeof(structshared_use_st),0666|IPC_CREAT);
if(shmid==-1)
{
fprintf(stderr,"shmget failed\n");
exit(EXIT_FAILURE);
}
/*映射共享内存*/
shared_memory=shmat(shmid,(void *)0,0);
if(shared_memory==(void *)-1)
{
fprintf(stderr,"shmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at%X\n",(int)shared_memory);
/*让结构体指针指向这块共享内存*/
shared_stuff=(struct shared_use_st*)shared_memory;
/*循环的向共享内存中写数据,直到写入的为“end”为止*/
while(running)
{
while(shared_stuff->written_by_you==1)
{
sleep(1);//等到读进程读完之后再写
printf("waiting forclient...\n");
}
printf("Ener some text:");
fgets(buffer,BUFSIZ,stdin);
strncpy(shared_stuff->some_text,buffer,TEXT_SZ);
shared_stuff->written_by_you=1;
if(strncmp(buffer,"end",3)==0)
{
running=0; //结束循环
}
}
/*删除共享内存*/
if(shmdt(shared_memory)==-1)
{
fprintf(stderr,"shmdt failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
shm_com.h
#define TEXT_SZ 2048
struct shared_use_st
{
int written_by_you;
char some_text[TEXT_SZ];
};
IPC方法—消息队列
输入程序7-12和7-13,编译执行并写出结果。
实验主要流程、基本操作或核心代码、算法片段
7-1
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void ouch(int sig)
{
printf("OUCH! - I got signal %d\n", sig);
}
int main()
{
struct sigaction act;
act.sa_handler = ouch;
//创建空的信号屏蔽字,即不屏蔽任何信息
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGINT, &act, 0);
while(1) {
printf("Hello World!\n");
sleep(1);
}
}
7-2
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void ouch(int sig)
{
printf("OUCH! - I got signal %d\n", sig);
(void) signal(SIGINT, SIG_DFL);
}
int main()
{
(void) signal(SIGINT, ouch);
while(1) {
printf("Hello World!\n");
sleep(1);
}
}
7-3—lucyToPeter.c
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int pipe1_fd[2], pipe2_fd[2];
char parent_buf[256], child_buf[256];
int len;
int child_status;
if(pipe(pipe1_fd)<0)
{
printf("pipe1 create error\n");
return -1;
}
if(pipe(pipe2_fd)<0)
{
printf("pipe2 create error\n");
return -1;
}
if(fork()==0) //child
{
printf("\n");
//pipe1_fd[0] is used to read, pipe2_fd[1] is used to write
close(pipe1_fd[1]);
close(pipe2_fd[0]);
while(1)
{
len = read(pipe1_fd[0], child_buf, 255);
child_buf[len] = '\0';
printf("peter_Lucy: %s\n", child_buf);
printf("Peter: ");
fgets(child_buf, 256, stdin);
child_buf[strlen(child_buf)-1] = '\0';
if (strncmp(child_buf,"quit", 4) == 0) {
close(pipe1_fd[0]);
close(pipe2_fd[1]);
exit(0);
}
write(pipe2_fd[1], child_buf, strlen(child_buf));
sleep(1);
}
close(pipe1_fd[0]);
close(pipe2_fd[1]);
exit(0);
}
else { //parent
//pipe1_fd[1] is used to write, pipe2_fd[0] is used to read
close(pipe1_fd[0]);
close(pipe2_fd[1]);
while (1) {
printf("Lucy: ");
fgets(parent_buf, 256, stdin);
if (strncmp(parent_buf,"quit", 4) == 0) {
close(pipe1_fd[1]);
close(pipe2_fd[0]);
exit(0);
}
write(pipe1_fd[1],parent_buf,strlen(parent_buf));
sleep(1);
len = read(pipe2_fd[0],parent_buf,255);
parent_buf[len] = '\0';
printf("Lucy_peter: %s\n", parent_buf);
}
close(pipe1_fd[1]);
close(pipe2_fd[0]);
wait(&child_status);
exit(0);
}
}
7-4—lucy.c
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
char write_fifo_name[] = "write-fifo";
char read_fifo_name[] = "read-fifo";
int write_fd, read_fd;
char buf[256];
int len;
struct stat stat_buf;
int ret = mkfifo(write_fifo_name, S_IRUSR | S_IWUSR);
if ( ret == -1) {
printf("Fail to create FIFO %s: %s", write_fifo_name, strerror(errno));
exit(-1);
}
write_fd = open(write_fifo_name, O_WRONLY);
if (write_fd == -1) {
printf("Fail to open FIFO %s: %s", write_fifo_name, strerror(errno));
exit(-1);
}
while ((read_fd = open(read_fifo_name, O_RDONLY)) == -1) {
sleep(1);
}
while (1) {
printf("Lucy: ");
fgets(buf, 256, stdin);
buf[strlen(buf)-1] = '\0';
if (strncmp(buf,"quit", 4) == 0) {
close(write_fd);
unlink(write_fifo_name);
close(read_fd);
exit(0);
}
write(write_fd, buf, strlen(buf));
len = read(read_fd, buf, 256);
if ( len > 0) {
buf[len] = '\0';
printf("Peter: %s\n", buf);
}
}
}
7-5—peter.c
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
int main()
{
char write_fifo_name[] = "read-fifo";
char read_fifo_name[] = "write-fifo";
int write_fd, read_fd;
char buf[256];
int len;
int ret = mkfifo(write_fifo_name, S_IRUSR | S_IWUSR);
if ( ret == -1) {
printf("Fail to create FIFO %s: %s", write_fifo_name, strerror(errno));
exit(-1);
}
while ((read_fd = open(read_fifo_name, O_RDONLY)) == -1) {
sleep(1);
}
write_fd = open(write_fifo_name, O_WRONLY);
if (write_fd == -1) {
printf("Fail to open FIFO %s: %s", write_fifo_name, strerror(errno));
exit(-1);
}
while (1) {
len = read(read_fd, buf, 256);
if ( len > 0) {
buf[len] = '\0';
printf("Lucy: %s\n", buf);
}
printf("Peter: ");
fgets(buf, 256, stdin);
buf[strlen(buf)-1] = '\0';
if (strncmp(buf,"quit", 4) == 0) {
close(write_fd);
unlink(write_fifo_name);
close(read_fd);
exit(0);
}
write(write_fd, buf, strlen(buf));
}
}
7-6—semun.h
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* union semun is defined by including <sys/sem.h> */
#else
/* according to X/OPEN we have to define it ourselves */
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short int *array; /* array for GETALL, SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
#endif
7-7—sem1.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
//应用程序必须再定义一遍
#include "semun.h"
static int set_semvalue(void);
static void del_semvalue(void);
static int semaphore_p(void);
static int semaphore_v(void);
static int sem_id;
int main(int argc, char *argv[])
{
int i;
int pause_time;
char op_char = 'O';
srand((unsigned int)getpid());
//创建信号量集,信号量集id是1234,信号量集中只有一个信号量,一个信号量代表一种共享资源[[stdout]]
sem_id = semget((key_t)1234, 1, 0666 | IPC_CREAT);
printf("semid = %d\n",sem_id);
if (argc > 1) { //必须要有一个进程启动时argc大于1,来set_semvalue(),否则参数argc=1的进程会一直阻塞在line 53:semaphore_p()
if (!set_semvalue()) { //程序第一次被调用,初始化信号量
fprintf(stderr, "Failed to initialize semaphore\n");
exit(EXIT_FAILURE);
}
//设置要输出到屏幕中的信息,即其参数的第一个字符
op_char = 'X';
sleep(5);
}
/* Then we have a loop which enters and leaves the critical section ten times.
There, we first make a call to semaphore_p which sets the semaphore to wait, as
this program is about to enter the critical section. */
for(i = 0; i < 10; i++) {
//进入临界区
if (!semaphore_p()) exit(EXIT_FAILURE);
//向屏幕中输出数据
printf("%c", op_char);fflush(stdout);
//清理缓冲区,然后休眠随机时间
pause_time = rand() % 3;
sleep(pause_time);
//离开临界区前再一次向屏幕输出数据
printf("%c", op_char);fflush(stdout);
//离开临界区,休眠随机时间后继续循环
if (!semaphore_v()) exit(EXIT_FAILURE);
pause_time = rand() % 2;
sleep(pause_time);
}
printf("\n%d - finished\n", getpid());
if (argc > 1) {
sleep(10);
del_semvalue();
}
exit(EXIT_SUCCESS);
}
/* The function set_semvalue initializes the semaphore using the SETVAL command in a semctl call. We need to do this before we can use the semaphore. */
static int set_semvalue(void)
{
union semun sem_union;
sem_union.val = 1;
if (semctl(sem_id, 0, SETVAL, sem_union) == -1) return(0);
return(1);
}
/* The del_semvalue function has almost the same form, except the call to semctl uses the command IPC_RMID to remove the semaphore's ID. */
static void del_semvalue(void)
{
union semun sem_union;
if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
fprintf(stderr, "Failed to delete semaphore\n");
}
/* semaphore_p changes the semaphore by -1 (waiting). */
static int semaphore_p(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1; /* P() */
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id, &sem_b, 1) == -1) {
fprintf(stderr, "semaphore_p failed\n");
return(0);
}
return(1);
}
/* semaphore_v is similar except for setting the sem_op part of the sembuf structure to 1, so that the semaphore becomes available. */
static int semaphore_v(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1; /* V() */
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id, &sem_b, 1) == -1) {
fprintf(stderr, "semaphore_v failed\n");
return(0);
}
return(1);
}
7-8—lucy2.c
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#if defined(_GNU_LIBRARY_) && !defined(_SEM_SEMUN_UNDEFINED)
/* union semun is defined by including <sys/sem.h> */
#else
/* according to X/OPEN we have to define it ourselves */
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* array for GETALL, SETALL */
/* Linux specific part: */
struct seminfo *_buf; /* buffer for IPC_INFO */
};
#endif
#define PROJID 0xFF
int semid;
void terminate_handler(int signo)
{
semctl(semid, 0, IPC_RMID);
exit(0);
}
int main(void)
{
char filenm[] = "shared-file";
char zero_blk[4096];
char * mmap_addr;
int fd;
key_t semkey;
struct sembuf getsem, setsem;
union semun seminit;
int ret;
semkey = ftok(filenm, PROJID);
if (semkey == -1) {
perror("ftok error: ");
exit(-1);
}
semid = semget(semkey, 2, IPC_CREAT | IPC_EXCL | 0666);
if (semid == -1) {
perror("semget error: ");
exit(-1);
}
seminit.val = 0;
semctl(semid, 0, SETVAL, seminit);
semctl(semid, 1, SETVAL, seminit);
getsem.sem_num = 1;
getsem.sem_op = -1;
getsem.sem_flg = SEM_UNDO;
setsem.sem_num = 0;
setsem.sem_op = 1;
setsem.sem_flg = SEM_UNDO;
signal(SIGINT, terminate_handler);
signal(SIGTERM, terminate_handler);
memset(zero_blk, 0, 4096);
fd = open(filenm, O_RDWR | O_CREAT);
if (fd == -1) {
perror("open error: ");
semctl(semid, 0, IPC_RMID);
exit(-1);
}
write(fd, zero_blk, 4096);
mmap_addr = (char *)mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mmap_addr == (char *)-1) {
perror("mmap error: ");
semctl(semid, 0, IPC_RMID);
close(fd);
exit(-1);
}
while (1) {
printf("Lucy: ");
fgets(mmap_addr, 256, stdin);
if (strncmp("quit", mmap_addr, 4) == 0) {
if (munmap(mmap_addr, 4096) == -1) {
perror("munmap error: ");
}
close(fd);
semctl(semid, 0, IPC_RMID);
exit(0);
}
mmap_addr[strlen(mmap_addr)-1] = '\0';
ret = semop(semid, &setsem, 1);
if (ret == -1) {
perror("semop error: ");
}
ret = semop(semid, &getsem, 1);
if (ret == -1) {
perror("semop error: ");
}
printf("Peter: %s\n", mmap_addr);
}
}
7-9—peter2.c
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>
#include <stdlib.h>
#define PROJID 0xFF
int main(void)
{
char filenm[] = "shared-file";
char * mmap_addr;
int fd, semid;
key_t semkey;
struct sembuf getsem, setsem;
semkey = ftok(filenm, PROJID);
if (semkey == -1) {
perror("ftok error: ");
exit(-1);
}
semid = semget(semkey, 0, 0);
if (semid == -1) {
perror("semget error: ");
exit(-1);
}
getsem.sem_num = 0;
getsem.sem_op = -1;
getsem.sem_flg = SEM_UNDO;
setsem.sem_num = 1;
setsem.sem_op = 1;
setsem.sem_flg = SEM_UNDO;
fd = open(filenm, O_RDWR | O_CREAT);
if (fd == -1) {
perror("open error: ");
semctl(semid, 0, IPC_RMID);
exit(-1);
}
mmap_addr = (char *)mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mmap_addr == (char *)-1) {
perror("mmap error: ");
close(fd);
exit(-1);
}
while (1) {
semop(semid, &getsem, 1);
printf("Lucy: %s\n", mmap_addr);
printf("Peter: ");
fgets(mmap_addr, 256, stdin);
if (strncmp("quit", mmap_addr, 4) == 0) {
mmap_addr[strlen(mmap_addr)-1] = '\0';
semop(semid, &setsem, 1);
if (munmap(mmap_addr, 4096) == -1) {
perror("munmap error: ");
}
close(fd);
exit(0);
}
mmap_addr[strlen(mmap_addr)-1] = '\0';
semop(semid, &setsem, 1);
}
}
7-10(可用上面的du.c代替)
/* Our first program is a consumer. After the headers the shared memory segment
(the size of our shared memory structure) is created with a call to shmget,
with the IPC_CREAT bit specified. */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"
int main()
{
int running = 1;
void *shared_memory = (void *)0;
struct shared_use_st *shared_stuff;
int shmid;
srand((unsigned int)getpid());
/*创建共享内存*/
shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);
if (shmid == -1) {
fprintf(stderr, "shmget failed\n");
exit(EXIT_FAILURE);
}
/*映射共享内存*/
shared_memory = shmat(shmid, (void *)0, 0);
if (shared_memory == (void *)-1) {
fprintf(stderr, "shmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %X\n", (int)shared_memory);
/* The next portion of the program assigns the shared_memory segment to shared_stuff,
which then prints out any text in written_by_you. The loop continues until end is found
in written_by_you. The call to sleep forces the consumer to sit in its critical section,
which makes the producer wait. */
/*让结构体指针指向这块共享内存*/
shared_stuff = (struct shared_use_st *)shared_memory;
/*控制读写顺序*/
shared_stuff->written_by_you = 0;
/*循环的从共享内存中读数据,直到读到“end”为止*/
while(running) {
if (shared_stuff->written_by_you) {
printf("You wrote: %s", shared_stuff->some_text);
sleep(1); //读进程睡1秒,同时会导致写进程睡一秒,这样做到读了之后再写
shared_stuff->written_by_you = 0;
if (strncmp(shared_stuff->some_text, "end", 3) == 0) {
running = 0; //结束循环
}
}
}
/*删除共享内存*/
if (shmdt(shared_memory) == -1) {
fprintf(stderr, "shmdt failed\n");
exit(EXIT_FAILURE);
}
if (shmctl(shmid, IPC_RMID, 0) == -1) {
fprintf(stderr, "shmctl(IPC_RMID) failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
7-11(可用上面的xie.c代替)
/* The second program is the producer and allows us to enter data for consumers.
It's very similar to shm1.c and looks like this. */
//写进程
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"
int main()
{
int running = 1;
void *shared_memory = (void *)0;
struct shared_use_st *shared_stuff;
char buffer[BUFSIZ];
int shmid;
shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);
if (shmid == -1) {
fprintf(stderr, "shmget failed\n");
exit(EXIT_FAILURE);
}
shared_memory = shmat(shmid, (void *)0, 0);
if (shared_memory == (void *)-1) {
fprintf(stderr, "shmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %X\n", (int)shared_memory);
shared_stuff = (struct shared_use_st *)shared_memory;
while(running) {
while(shared_stuff->written_by_you == 1) {
sleep(1);
printf("waiting for client...\n");
}
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
strncpy(shared_stuff->some_text, buffer, TEXT_SZ);
shared_stuff->written_by_you = 1;
if (strncmp(buffer, "end", 3) == 0) {
running = 0;
}
}
if (shmdt(shared_memory) == -1) {
fprintf(stderr, "shmdt failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
shm_com.h
#define TEXT_SZ 2048
struct shared_use_st
{
int written_by_you;
char some_text[TEXT_SZ];
};
7-12—lucy3.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <signal.h>
#define PROJID 0xFF
#define SNDMSG 1
#define RCVMSG 2
int mqid;
void terminate_handler(int signo)
{
msgctl(mqid, IPC_RMID, NULL);
exit(0);
}
int main(void)
{
char filenm[] = "shared-file";
key_t mqkey;
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[256]; /* message data */
}msg;
int ret;
mqkey = ftok(filenm, PROJID);
if (mqkey == -1) {
perror("ftok error: ");
exit(-1);
}
mqid = msgget(mqkey, IPC_CREAT | IPC_EXCL | 0666);
if (mqid == -1) {
perror("msgget error: ");
exit(-1);
}
signal(SIGINT, terminate_handler);
signal(SIGTERM, terminate_handler);
while (1) {
printf("Lucy: ");
fgets(msg.mtext, 256, stdin);
if (strncmp("quit", msg.mtext, 4) == 0) {
msgctl(mqid, IPC_RMID, NULL);
exit(0);
}
msg.mtext[strlen(msg.mtext)-1] = '\0';
msg.mtype = SNDMSG;
msgsnd(mqid, &msg, strlen(msg.mtext) + 1, 0);
msgrcv(mqid, &msg, 256, RCVMSG, 0);
printf("Peter: %s\n", msg.mtext);
}
}
7-13—peter3.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <signal.h>
#define PROJID 0xFF
#define SNDMSG 1
#define RCVMSG 2
int main(void)
{
char filenm[] = "shared-file";
int mqid;
key_t mqkey;
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[256]; /* message data */
}msg;
int ret;
mqkey = ftok(filenm, PROJID);
if (mqkey == -1) {
perror("ftok error: ");
exit(-1);
}
mqid = msgget(mqkey, 0);
if (mqid == -1) {
perror("msgget error: ");
exit(-1);
}
while (1) {
msgrcv(mqid, &msg, 256, SNDMSG, 0);
printf("Lucy: %s\n", msg.mtext);
printf("Peter: ");
fgets(msg.mtext, 256, stdin);
if (strncmp("quit", msg.mtext, 4) == 0) {
exit(0);
}
msg.mtext[strlen(msg.mtext)-1] = '\0';
msg.mtype = RCVMSG;
msgsnd(mqid, &msg, strlen(msg.mtext) + 1, 0);
}
}