思维导图&笔记:
笔记见我的博客: 链接
作业
1> 使用消息队列完成两个进程之间相互通信
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <pthread.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int userid = 0;
char username1[128];
char username2[128];
// 定义消息结构体类型
struct message
{
long mtype; // 消息类型
char mtext[4096]; // 消息正文
};
// 1、创建key值
key_t key = 0;
// 2、使用key值创建一个消息队列
int msgid = 0;
// 定义一个宏,表示正文大小
#define SIZE (sizeof(struct msgbuf) - sizeof(long))
// 此时就已经在内核空间创建出消息队列了
// 发送消息的函数
void send_message(int msgid, long mtype, const char *sender, const char *receiver)
{
struct message msg;
msg.mtype = mtype;
printf("[%s] Enter a message for %s: ", sender, receiver);
fgets(msg.mtext, sizeof(msg.mtext), stdin);
// 发送消息
if (msgsnd(msgid, &msg, sizeof(msg.mtext), 0) == -1)
{
perror("msgsnd");
exit(EXIT_FAILURE);
}
}
// 接收消息的函数
void receive_message(int msgid, long mtype, const char *receiver)
{
struct message msg;
// 接收消息
if (msgrcv(msgid, &msg, sizeof(msg.mtext), mtype, 0) == -1)
{
perror("msgrcv");
exit(EXIT_FAILURE);
}
// 打印接收到的消息
printf("[%s] Received message: %s\n", receiver, msg.mtext);
}
void *receive(void *arg)
{
// 3、循环向消息队列中存放数据
while (1)
{
receive_message(msgid, 2, username1);
}
}
void *send(void *arg)
{
send_message(msgid, 1, username1, username2);
}
int main(int argc, const char *argv[])
{
if ((key = ftok("/", 'a')) == -1)
{
perror("fork error");
return -1;
}
if ((msgid = msgget(key, IPC_CREAT | 0664)) == -1)
{
perror("msgget error");
return -1;
}
printf("请输入您的用户名:");
fgets(username1,sizeof(username1), stdin);
// printf("等待其他用户上线。\n");
printf("请输入对方的用户名:");
fgets(username2,sizeof(username2), stdin);
pthread_t tid1, tid2;
if (pthread_create(&tid1, NULL, receive, NULL) != 0)
{
printf("tid1 creat error\n");
return -1;
}
if (pthread_create(&tid2, NULL, send, NULL) != 0)
{
printf("tid1 creat error\n");
return -1;
}
printf("线程创建成功!\n");
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
2> 将信号通信相关代码重新实现一遍
#include<myhead.h>
//定义信号处理函数
void handler(int signum)
{
if(signum == SIGINT) //表明要处理2号信号
{
printf("用户按下了ctrl + c键\n");
}
if(signum == SIGTSTP) //处理暂停信号
{
printf("用户按下了ctrl + z键\n");
}
}
/****************************主程序********************/
int main(int argc, const char *argv[])
{
/*将SIGINT信号忽略
if(signal(SIGINT, SIG_IGN) == SIG_ERR)
{
perror("signal error");
return -1;
}
*/
/*将SIGINT信号默认处理
if(signal(SIGINT, SIG_DFL) == SIG_ERR)
{
perror("signal error");
return -1;
}
*/
//将SIGINT信号捕获
if(signal(SIGINT, handler) == SIG_ERR)
{
perror("signal error");
return -1;
}
//绑定SIGTSTP信号 ctrl + z
if(signal(SIGTSTP, handler) == SIG_ERR)
{
perror("signal error");
return -1;
}
while(1)
{
sleep(1);
printf("我真的还想再活五百年\n");
}
return 0;
}
#include<myhead.h>
//定义信号处理函数
void handler(int signum)
{
if(signum == SIGINT) //表明要处理2号信号
{
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[])
{
/*尝试忽略SIGSTOP信号
if(signal(SIGSTOP, SIG_IGN) == SIG_ERR)
{
perror("signal error");
return -1;
}
*/
/*尝试捕获SIGSTOP信号
if(signal(SIGSTOP, handler) == SIG_ERR)
{
perror("signal error");
return -1;
}
*/
//尝试默认处理SIGSTOP信号
if(signal(SIGSTOP, SIG_DFL) == SIG_ERR)
{
perror("signal error");
return -1;
}
while(1)
{
sleep(1);
printf("我真的还想再活五百年\n");
}
return 0;
}
3> 将共享内存相关代码重新实现一遍
1> 发送端
#include<myhead.h>
#define PAGE_SIZE 4096
int main(int argc, const char *argv[])
{
//1、创建key值
key_t key = -1;
if((key = ftok("/", 't')) == -1)
{
perror("ftok error");
return -1;
}
printf("key = %#x\n", key);
//2、将物理内存创建出共享内存段
int shmid = 0;
if((shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664)) == -1)
{
perror("shmget error");
return -1;
}
printf("shmid = %d\n", shmid);
//3、将共享内存段地址映射到用户空间
//NULL表示让系统自动选择页的分段
//0表示当前进程对共享内存具有读写功能
char *addr = (char *)shmat(shmid, NULL, 0);
if(addr == (void *)-1)
{
perror("shmat error");
return -1;
}
printf("addr = %p\n", addr);
//4、操作共享内存
//char buf[128] = "";
while(1)
{
fgets(addr, PAGE_SIZE, stdin); //从终端输入数据
addr[strlen(addr) - 1] = '\0'; //将换行换成'\0'
if(strcmp(addr, "quit") == 0)
{
break;
}
}
//5、取消映射
while(1);
return 0;
}
2> 接收端
#include<myhead.h>
#define PAGE_SIZE 4096
int main(int argc, const char *argv[])
{
//1、创建key值
key_t key = -1;
if((key = ftok("/", 't')) == -1)
{
perror("ftok error");
return -1;
}
printf("key = %#x\n", key);
//2、将物理内存创建出共享内存段
int shmid = 0;
if((shmid = shmget(key, PAGE_SIZE, IPC_CREAT|0664)) == -1)
{
perror("shmget error");
return -1;
}
printf("shmid = %d\n", shmid);
//3、将共享内存段地址映射到用户空间
//NULL表示让系统自动选择页的分段
//0表示当前进程对共享内存具有读写功能
char *addr = (char *)shmat(shmid, NULL, 0);
if(addr == (void *)-1)
{
perror("shmat error");
return -1;
}
printf("addr = %p\n", addr);
//4、操作共享内存
//char buf[128] = "";
while(1)
{
printf("共享内存中的数据为:%s\n", addr);
sleep(1);
if(strcmp(addr, "quit") == 0)
{
break;
}
}
//5、取消映射
if(shmdt(addr) == -1)
{
perror("shmdt error");
return -1;
}
//6、删除共享内存
if(shmctl(shmid, IPC_RMID, NULL) == -1)
{
perror("shmctl error");
return -1;
}
return 0;
}