?1.使用消息队列完成两个进程之间相互通信
?2.信号通信相关代码的重新实现
(1)signal函数的实例
#include <head.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;
}
(2)尝试捕获SIGSTOP信号
#include <head.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)使用信号的方式以非阻塞的形式回收僵尸进程(SIGCHLD)
#include <head.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;
}
for(int i=0; i<10; i++)
{
if(fork() == 0)
{
exit(EXIT_SUCCESS);
}
}
while(1);
return 0;
}
(4)使用闹钟信号完成一个定时器(SIGALRM),该信号由alarm函数设置的时间超时后产生
#include <head.h>
int main(int argc, const char *argv[])
{
printf("%d\n", alarm(10)); //0
sleep(5);
printf("%d\n", alarm(10)); //5
while(1);
return 0;
}
(5)使用SIGALRM信号模拟斗地主出牌场景
#include <head.h>
//定义信号处理函数
void handler(int signo)
{
if(signo == SIGALRM)
{
printf("系统已经随机为您出一张牌\n");
alarm(5);
}
}
int main(int argc, const char *argv[])
{
char ch;
//将SIGALRM信号绑定到信号处理函数中
if(signal(SIGALRM, handler) == SIG_ERR)
{
perror("signal error");
return -1;
}
while(1)
{
alarm(5);
printf("请出牌:");
scanf("%c", &ch);
getchar();
printf("您出的牌为:%c\n", ch);
}
return 0;
}
(6)信号发送函数(kill、raise)
#include <head.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("我真的还想再活五百年\n");
sleep(1);
}
}else if(pid == 0)
{
//子进程
printf("人生得意须尽欢,莫使金樽空对月\n");
sleep(3);
printf("我看透了红尘, 父亲跟我一起走吧\n");
//向父进程发送一个信号
kill(getppid(), SIGUSR1);
exit(EXIT_SUCCESS); //退出进程
}else
{
perror("fork error");
return -1;
}
return 0;
}
3.共享内存相关代码重新实现
(1)发送端
#include <head.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 <head.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;
}