Day7
思维导图
作业
1、使用消息队列完成两个进程之间相互通信
代码
send.c
#include<myhead.h>
//定义消息结构体类型
struct msgbuf
{
long mtype; //消息类型
char mtext[64]; //消息正文
};
//定义一个宏,表示正文大小
#define SIZE (sizeof(struct msgbuf) - sizeof(long))
int main(int argc, const char *argv[])
{
//1、创建key值
key_t key = 0;
if((key = ftok("/", 't')) == -1)
{
perror("fork error");
return -1;
}
printf("key = %#x\n", key);
//2、使用key值创建一个消息队列
int msqid = 0;
if((msqid=msgget(key, IPC_CREAT|0664)) == -1)
{
perror("msgget error");
return -1;
}
printf("msqid = %d\n", msqid);
//此时就已经在内核空间创建出消息队列了
struct msgbuf buf;
pid_t pid=-1;
pid = fork();
if(pid>0)
{
//父进程
//定义一个消息类型的容器
//3、循环向消息队列中存放数据
while(1)
{
buf.mtype=2;
printf("请输入要存放的数据:");
fflush(stdout);
fgets(buf.mtext,64,stdin);
//将消息存放到消息队列中
msgsnd(msqid, &buf, SIZE, 0);
printf("发送成功\n");
if(strcmp(buf.mtext, "quit") == 0)
{
break;
}
}
wait(NULL);
}else if(pid==0)
{
//3、循环向消息队列中读取数据
while(1)
{
//从消息队列中读取消息
msgrcv(msqid, &buf, SIZE, 1, 0);
//第二个0表示阻塞形式接收消息
printf("收到消息为:%s\n", buf.mtext);
if(strcmp(buf.mtext, "quit") == 0)
{
break;
}
}
//4、删除消息队列
if(msgctl(msqid, IPC_RMID, NULL) == -1)
{
perror("msgctl error");
return -1;
}
exit(EXIT_SUCCESS);
}
else
{
perror("fork error");
return -1;
}
return 0;
}
receive.c
#include<myhead.h>
//定义消息结构体类型
struct msgbuf
{
long mtype; //消息类型
char mtext[64]; //消息正文
};
//定义一个宏,表示正文大小
#define SIZE (sizeof(struct msgbuf) - sizeof(long))
int main(int argc, const char *argv[])
{
//1、创建key值
key_t key = 0;
if((key = ftok("/", 't')) == -1)
{
perror("fork error");
return -1;
}
printf("key = %#x\n", key);
//2、使用key值创建一个消息队列
int msqid = 0;
if((msqid=msgget(key, IPC_CREAT|0664)) == -1)
{
perror("msgget error");
return -1;
}
printf("msqid = %d\n", msqid);
//此时就已经在内核空间创建出消息队列了
struct msgbuf buf;
pid_t pid=-1;
pid = fork();
if(pid>0)
{
//父进程
//3、循环向消息队列中存放数据
while(1)
{
buf.mtype=1;
printf("请输入要存放的数据:");
fflush(stdout);
fgets(buf.mtext,64,stdin);
//将消息存放到消息队列中
msgsnd(msqid, &buf, SIZE, 0);
printf("发送成功\n");
if(strcmp(buf.mtext, "quit") == 0)
{
break;
}
}
wait(NULL);
}else if(pid == 0)
{
//子进程
//3、循环向消息队列中读取数据
while(1)
{
//从消息队列中读取消息
msgrcv(msqid, &buf, SIZE, 2, 0);
//第二个0表示阻塞形式接收消息
printf("收到消息为:%s\n", buf.mtext);
if(strcmp(buf.mtext, "quit") == 0)
{
break;
}
}
//4、删除消息队列
if(msgctl(msqid, IPC_RMID, NULL) == -1)
{
perror("msgctl error");
return -1;
}
exit(EXIT_SUCCESS);
}else
{
perror("fork error");
return -1;
}
return 0;
}
运行结果
2、将信号通信相关代码重新实现一遍
代码
signal
#include <myhead.h>
void handler(int signum)
{
if(signum==SIGINT)
{
printf("用户按下ctrl+c键\n");
}
if(signum==SIGTSTP)
{
printf("用户按下ctrl+z键\n");
}
if(signum==SIGSTOP)
{
printf("用户按下ctrl+z键\n");
}
}
int main(int argc, const char *argv[])
{
/* if(signal(SIGINT,SIG_IGN)==SIG_ERR)
{
perror("signal error");
return -1;
}
*/
if(signal(SIGINT,SIG_DFL)==SIG_ERR)
{
perror("signal error");
return -1;
}
/*
if(signal(SIGINT,handler)==SIG_ERR)
{
perror("signal error");
return -1;
}
*/
while(1)
{
sleep(1);
printf("哈哈哈哈\n");
}
return 0;
}
信号发送函数
#include<myhead.h>
//定义信号处理函数
void handler(int signo)
{
if(signo == SIGUSR1)
{
printf("???\n");
raise(SIGKILL); //自杀
}
}
int main(int argc, const char *argv[])
{
//定义进程号
pid_t pid = fork();
if(pid > 0)
{
//父进程
//将SIGUSR1信号绑定
if(signal(SIGUSR1, handler) == SIG_ERR)
{
perror("signal error");
return -1;
}
while(1)
{
printf("nonono\n");
sleep(1);
}
}else if(pid == 0)
{
//子进程
printf("die\n");
sleep(3);
printf("die with me \n");
//向父进程发送一个信号
kill(getppid(), SIGUSR1);
exit(EXIT_SUCCESS); //退出进程
}else
{
perror("fork error");
return -1;
}
return 0;
}
3、将共享内存相关代码重新实现一遍
代码
send.c
#include<myhead.h>
#define PAGE_SIZE 4096
int main(int argc, const char *argv[])
{
//创建key值
key_t key = -1;
if((key = ftok("/", 't')) == -1)
{
perror("ftok error");
return -1;
}
printf("key = %#x\n", key);
//将物理内存创建出共享内存段
int shmid = 0;
if((shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664)) == -1)
{
perror("shmget error");
return -1;
}
printf("shmid = %d\n", shmid);
//将共享内存段地址映射到用户空间
//NULL表示让系统自动选择页的分段
//0表示当前进程对共享内存具有读写功能
char *addr = (char *)shmat(shmid, NULL, 0);
if(addr == (void *)-1)
{
perror("shmat error");
return -1;
}
printf("addr = %p\n", addr);
//操作共享内存
//char buf[128] = "";
while(1)
{
fgets(addr, PAGE_SIZE, stdin); //从终端输入数据
addr[strlen(addr) - 1] = '\0'; //将换行换成'\0'
if(strcmp(addr, "quit") == 0)
{
break;
}
}
//取消映射
if(shmdt(addr) == -1)
{
perror("shmdt error");
return -1;
}
//删除共享内存
if(shmctl(shmid, IPC_RMID, NULL) == -1)
{
perror("shmctl error");
return -1;
}
while(1);
return 0;
}
rece.c
#include<myhead.h>
#define PAGE_SIZE 4096
int main(int argc, const char *argv[])
{
//创建key值
key_t key = -1;
if((key = ftok("/", 't')) == -1)
{
perror("ftok error");
return -1;
}
printf("key = %#x\n", key);
//将物理内存创建出共享内存段
int shmid = 0;
if((shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664)) == -1)
{
perror("shmget error");
return -1;
}
printf("shmid = %d\n", shmid);
//将共享内存段地址映射到用户空间
//NULL表示让系统自动选择页的分段
//0表示当前进程对共享内存具有读写功能
char *addr = (char *)shmat(shmid, NULL, 0);
if(addr == (void *)-1)
{
perror("shmat error");
return -1;
}
printf("addr = %p\n", addr);
//操作共享内存
//char buf[128] = "";
while(1)
{
printf("共享内存中的数据为:%s\n", addr);
sleep(1);
if(strcmp(addr, "quit") == 0)
{
break;
}
}
//取消映射
if(shmdt(addr) == -1)
{
perror("shmdt error");
return -1;
}
//删除共享内存
if(shmctl(shmid, IPC_RMID, NULL) == -1)
{
perror("shmctl error");
return -1;
}
return 0;
}