慕尼黑0001808 的学生作业:
//创建两个子进程A与B,父进程分别给两个子进程发型消息,消息类型为 100 与 200
//父进程从键盘循环接收数据,发送给子进程,输入 quit 则退出
#include
#include
#include
#include
#include
#include
#include
#include
int msgid;
int pipe_a[2];
int pipe_b[2];
pid_t pid_a;
pid_t pid_b;
struct msg_struct {
long m_type;
char m_text[1024];
};
void signote_handler(int sinno){}
void child_process(int msg_type,char child_name) {
printf("子进程%c(pid=%d)启动,等待接收消息\n",child_name,getpid());
char flag = '1';
int m_mipe = child_name == 'A' ? pipe_a[1] : pipe_b[1];
struct msg_struct buf;
while (1) {
write(m_mipe,&flag,1);
pause();
if (msgrcv(msgid, &buf, sizeof(buf.m_text), msg_type, 0) == -1) {
perror("msgrcv()");
exit(EXIT_FAILURE);
}
printf("子进程%c(pid=%d)收到类型%d的消息: %s\n",child_name, getpid(), msg_type, buf.m_text);
}
exit(EXIT_SUCCESS);
}
void clean_up() {
msgctl(msgid, IPC_RMID, NULL);
printf("\n消息队列已清理\n");
kill(pid_a,SIGKILL);
kill(pid_b,SIGKILL);
waitpid(pid_a, NULL, 0);
waitpid(pid_b, NULL, 0);
}
int main() {
// 创建消息队列
key_t key = ftok(".", 'm');
if (key == -1) {
perror("ftok()");
exit(EXIT_FAILURE);
}
msgid = msgget(key, IPC_CREAT | 0666);
if (msgid == -1) {
perror("msgget()");
exit(EXIT_FAILURE);
}
// 设置信号处理
signal(SIGINT, clean_up);
signal(SIGUSR1,signote_handler);
// 创建无名管道
if(-1 == pipe(pipe_a)){
perror("Apipe()");
exit(EXIT_FAILURE);
}
if(-1 == pipe(pipe_b)){
perror("Bpipe()");
exit(EXIT_FAILURE);
}
// 清屏并设置初始界面
printf("父进程(pid=%d)启动,输入消息内容(输入'quit'退出):\n", getpid());
// 创建子进程A
pid_a = fork();
if (pid_a == -1) {
perror("fork A failed");
exit(EXIT_FAILURE);
} else if (pid_a == 0) {
close(pipe_a[0]);
child_process(100,'A');
}
// 创建子进程B
pid_b = fork();
if (pid_b == -1) {
perror("fork B failed");
exit(EXIT_FAILURE);
} else if (pid_b == 0) {
close(pipe_b[0]);
child_process(200,'B');
}
struct msg_struct buf;
char flag;
// 主循环
while (1) {
read(pipe_a[0],&flag,1);
read(pipe_b[0],&flag,1);
printf("> ");
// 读取输入
if (fgets(buf.m_text, sizeof(buf.m_text), stdin) == NULL) {
perror("fgets()");
break;
}
// 处理换行符
buf.m_text[strcspn(buf.m_text, "\n")] = '\0';
// 检查退出条件
if (strcmp(buf.m_text, "quit") == 0) {
break;
}
// 发送消息给A
buf.m_type = 100;
if (msgsnd(msgid, &buf, strlen(buf.m_text)+1, 0) == -1) {
perror("msgsnd to A failed");
break;
}
// 发送消息给B
buf.m_type = 200;
if (msgsnd(msgid, &buf, strlen(buf.m_text)+1, 0) == -1) {
perror("msgsnd to B failed");
break;
}
printf("父进程(pid=%d)发送消息成功: %s\n", getpid(), buf.m_text);
kill(pid_a,SIGUSR1);
kill(pid_b,SIGUSR1);
}
// 清理资源
clean_up();
printf("父进程(pid=%d)正常退出\n", getpid());
return 0;
}
运行结果:
linux@linux-VMware-Virtual-Platform:~/study/homework/10416$ ./a.out
父进程(pid=102869)启动,输入消息内容(输入'quit'退出):
子进程A(pid=102870)启动,等待接收消息
子进程B(pid=102871)启动,等待接收消息
> hello
父进程(pid=102869)发送消息成功: hello
子进程A(pid=102870)收到类型100的消息: hello
子进程B(pid=102871)收到类型200的消息: hello
> quit
消息队列已清理
父进程(pid=102869)正常退出
linux@linux-VMware-Virtual-Platform:~/study/homework/10416$ ./a.out
父进程(pid=102877)启动,输入消息内容(输入'quit'退出):
子进程A(pid=102878)启动,等待接收消息
子进程B(pid=102879)启动,等待接收消息
> ^C
消息队列已清理
已杀死
linux@linux-VMware-Virtual-Platform:~/study/homework/10416$