思维导图
练习题
1> 使用消息队列完成两个进程之间相互通信
程序1
#include <myhead.h>
#define SIZE 1024
//创建消息队列所需的结构体
typedef struct msgbuf
{
long msgtype;
char msgtext[SIZE];
} msgBuf;
//线程1函数完成发送消息
void *task1(void *arg)
{
//创建key
key_t key = ftok("/", 1);
if (key == -1)
{
perror("create key error");
return NULL;
}
//获取消息队列,如果没有创建消息队列
int msqid = msgget(key, IPC_CREAT | 0664);
if (msqid == -1)
{
perror("create msgget error");
return NULL;
}
//设置结构体中数据类型
msgBuf buf = {.msgtype = 1};
//循环写入消息到消息队列中
while (1)
{
printf("input:");
//结构体msgtext从终端获取内容
scanf(" %s", buf.msgtext);
//将内容写入对应msqid的消息队列中
msgsnd(msqid, &buf, sizeof(buf.msgtext), 0);
//输入quit退出循环输入
if (strcmp(buf.msgtext, "quit") == 0)
break;
}
//删除消息队列
msgctl(msqid, IPC_RMID, NULL);
}
//线程2函数完成接收消息
void *task2(void *arg)
{
//创建和发送端一样的key
key_t key = ftok("/", 2);
if (key == -1)
{
perror("create key error");
return NULL;
}
//创建消息队列
int msqid = msgget(key, IPC_CREAT | 0664);
if (msqid == -1)
{
perror("create msgid error");
return NULL;
}
msgBuf buf = {.msgtype = 2};
while (1)
{
//获取消息队列中的内容
msgrcv(msqid, &buf, sizeof(buf.msgtext), 0, 0);
printf("\noutput:%s\n", buf.msgtext);
if (strcmp(buf.msgtext, "quit") == 0)
break;
}
}
int main(int argc, char const *argv[])
{
//创建线程名
pthread_t tid1, tid2;
if (pthread_create(&tid1, NULL, task1, NULL) == -1)
{
printf("create tid1 error");
return -1;
}
if (pthread_create(&tid2, NULL, task2, NULL) == -1)
{
printf("create tid1 error");
return -1;
}
//回收线程资源
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
程序2
#include <myhead.h>
#define SIZE 1024
//创建消息队列所需的结构体
typedef struct msgbuf
{
long msgtype;
char msgtext[SIZE];
} msgBuf;
//线程1函数完成发送消息
void *task1(void *arg)
{
//创建key
key_t key = ftok("/", 2);
if (key == -1)
{
perror("create key error");
return NULL;
}
//获取消息队列,如果没有创建消息队列
int msqid = msgget(key, IPC_CREAT | 0664);
if (msqid == -1)
{
perror("create msgget error");
return NULL;
}
//设置结构体中数据类型
msgBuf buf = {.msgtype = 2};
//循环写入消息到消息队列中
while (1)
{
printf("input:");
//结构体msgtext从终端获取内容
scanf(" %s", buf.msgtext);
//将内容写入对应msqid的消息队列中
msgsnd(msqid, &buf, sizeof(buf.msgtext), 0);
//输入quit退出循环输入
if (strcmp(buf.msgtext, "quit") == 0)
break;
}
//删除消息队列
msgctl(msqid, IPC_RMID, NULL);
}
//线程2函数完成接收消息
void *task2(void *arg)
{
//创建和发送端一样的key
key_t key = ftok("/", 1);
if (key == -1)
{
perror("create key error");
return NULL;
}
//创建消息队列
int msqid = msgget(key, IPC_CREAT | 0664);
if (msqid == -1)
{
perror("create msgid error");
return NULL;
}
msgBuf buf = {.msgtype = 1};
while(1)
{
//获取消息队列中的内容
msgrcv(msqid,&buf,sizeof(buf.msgtext),0,0);
printf("\noutput:%s\n",buf.msgtext);
if(strcmp(buf.msgtext,"quit")==0) break;
}
}
int main(int argc, char const *argv[])
{
//创建线程名
pthread_t tid1, tid2;
if (pthread_create(&tid1, NULL, task1, NULL) == -1)
{
printf("create tid1 error");
return -1;
}
if (pthread_create(&tid2, NULL, task2, NULL) == -1)
{
printf("create tid1 error");
return -1;
}
//回收线程资源
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
2> 将信号通信相关代码实现
#include <myhead.h>
int main(int argc, char const *argv[])
{
//信号处理的3种方式,默认执行(一般为杀死进程)、忽略、捕获
//绑定从终端获取的信号,默认执行信号内容
if(signal(SIGINT,SIG_DFL)==SIG_ERR)
{
perror("绑定失败");
return -1;
}
int i=0;
while(1)
{
sleep(1);
i++;
printf("%d\n",i);
}
return 0;
}
#include <myhead.h>
int main(int argc, char const *argv[])
{
//信号处理的3种方式,默认执行(一般为杀死进程)、忽略、捕获
//绑定从终端获取的信号,忽略信号内容
if(signal(SIGINT,SIG_IGN)==SIG_ERR)
{
perror("绑定失败");
return -1;
}
int i=0;
while(1)
{
sleep(1);
i++;
printf("%d\n",i);
}
return 0;
}
#include <myhead.h>
void handler(int signum)
{
if(signum==SIGINT)
{
puts("按下Ctrl+C");
}
}
int main(int argc, char const *argv[])
{
//信号处理的3种方式,默认执行(一般为杀死进程)、忽略、捕获
//绑定从终端获取的信号,捕获信号内容
if(signal(SIGINT,handler)==SIG_ERR)
{
perror("绑定失败");
return -1;
}
int i=0;
while(1)
{
sleep(1);
i++;
printf("%d\n",i);
}
return 0;
}
#include <myhead.h>
//定义信号处理函数
void handler(int signum)
{
if (signum == SIGCHLD)
{
//以非阻塞的形式回收僵尸进程,直到所有的僵尸进程全部回收结束
while (waitpid(-1, NULL, WNOHANG) > 0);
}
}
int main(int argc, const char *argv[])
{
//捕获子进程发来的SIGCHLD信号
if (signal(SIGCHLD, handler) == SIG_ERR)
{
perror("signal error");
return -1;
}
//创建5个子进程并杀死,成为僵尸进程
for (int i = 0; i < 4; i++)
{
if (fork() == 0)
{
exit(EXIT_SUCCESS);
}
}
//父进程阻塞,不会回收子进程
while (1);
return 0;
}
#include <myhead.h>
void handler(int signo)
{
if(signo==SIGUSR1)
{
puts("就这样活");
//杀死父进程
raise(SIGKILL);
}
}
int main(int argc, char const *argv[])
{
//创建子进程
pid_t pid = fork();
if (pid > 0)
{
//当父进程等待SIGUSER1发来信号,然后捕获信号,执行handler函数
if(signal(SIGUSR1,handler)==SIG_ERR)
{
perror("signal error");
return -1;
}
//阻塞父进程
while (1)
{
puts("活着");
sleep(1);
}
}
else if (pid == 0)
{
puts("好");
sleep(3);
puts("怎么活");
//子进程发送kill信号
kill(getppid(), SIGUSR1);
exit(0);
}
else
{
perror("create pid error");
return -1;
}
return 0;
}
3> 将共享内存相关代码实现
发送端
#include <myhead.h>
#define PAGE_SIZE 4096
int main(int argc, char const *argv[])
{
//创建key
key_t key = ftok("/", 1);
//打印key的地址
printf("key=%x\n", key);
//申请物理内存,映射共享内存空间
int shmid = shmget(key, PAGE_SIZE, IPC_CREAT | 0664);
if (shmid == -1)
{
perror("shmget error");
return -1;
}
//打印内存空间
printf("shmid=%d\n", shmid);
//映射共享空间
char *addr = (char *)shmat(shmid, NULL, 0);
//打印地址
printf("addr=%p\n", addr);
//操作共享内存
while (1)
{
fgets(addr, PAGE_SIZE, stdin); //从终端输入数据
addr[strlen(addr) - 1] = '\0'; //将换行换成'\0'
if (strcmp(addr, "quit") == 0)
{
break;
}
}
return 0;
}
接收端
#include <myhead.h>
#define PAGE_SIZE 4096
int main(int argc, const char *argv[])
{
//创建key值
key_t key = key = ftok("/", 1);
printf("key = %x\n", key);
//2、将物理内存创建出共享内存段
int shmid = shmget(key, PAGE_SIZE, IPC_CREAT | 0664);
if (shmid == -1)
{
perror("shmget error");
return -1;
}
printf("shmid = %d\n", shmid);
//将共享内存段地址映射到用户空间
//NULL表示让系统自动选择页的分段
//0表示当前进程对共享内存具有读写功能
char *addr = (char *)shmat(shmid, NULL, 0);
printf("addr = %p\n", addr);
//操作共享内存
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;
}