进程间通信的几种方法
1 文件(效率低,基本不使用)
2 管道 (在文件的基础上改进的方式)
3 信号 (效率较高,但是传输数据不方便,只能传输整形数,有点像中断)
4 IPC通信(消息队列和共享内存)
信号量(不负责通信,只负责保护通信时的安全,也是IPC)
管道通信
无名管道:只用于父子进程之间的通信。
有名管道:可用于不同进程之间的通信。(也可以用于父子之间)
管道文件不是可以无穷写入的,当管道写满后,写函数会阻塞(等待读取)
无名管道的创建
int pipe(int pipefd【2】)
arg1 无名管道的两个端口(读和写)
即1为写端,0为读端。需要进程间配合使用。
int main()
{
//创建一个无名管道
int pipefd[2]={0};
int fd=pipe(pipefd);
if(fd != 0)
{
perror("创建管道失败\n");
exit(0);
}
else
{
printf("创建管道成功\n");
}
int len=0;
char buf[10]={0};
while(1)
{
/*
//写入数据到管道中
int ret=write(pipefd[1],"abcd",4);
printf("len=%d\n",len+=ret);
if(ret < 0)
{
perror("");
}
*/
//自己读走
read(pipefd[0],buf,10);
printf("get:%s\n",buf);
}
}
有名管道的创建
1 使用命令的方式创建
mkfifo 文件名
(共享目录不支持管道文件)
2 函数创建
int mkfifo(const char *pathname,mod_t mode);
arg1 需要创建的管道路径
arg2 权限
int fd=mkfifo("/home/gec/pipe",0777);
if(fd != 0)
{
perror("创建管道失败\n");
}
有名管道的操作
1 open 打开管道文件
2 write/read 读写管道
3 close 关闭管道
注意事项:1 管道文件的数据时先进先出的
2 管道文件的读写都会阻塞
3 管道文件不可以用lseek偏移光标
int fd = open("/home/gec/pipenode",O_RDWR);
if(fd < 0)
{
perror("open pipe fail\n");
exit(0);
}
//不断往管道中写入数据
int len=0;
while(1)
{
int ret=write(fd,"123456",6);
printf("len=%d\n",len+=ret);
}
信号
信号的命令
man 7 signal查看
抓捕linux系统中的信号
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
参数一:需要捕抓信号值
参数二:对应的处理函数
SIG_IGN ->忽略该信号
SIG_DFL ->执行默认动作
用户自定义动作void (*sighandler_t)(int) -> 函数指针,指向返回类型为 void 参数为int的函数 (处理函数)
信号发送
void func(int arg)
{
printf("arg=%d\n",arg); //arg 当前触发的信号值
printf("你杀不死我!\n");
}
int main()
{
//修改ctrl c对应的动作,当进程收到ctrl c后就输出,”你杀不死我!“
//忽略ctrl c
signal(SIGINT,func);
int i=0;
while(1)
{
printf("i=%d\n",i++);
if(i%3 == 0)
{
//发送一个信号出去
kill(getpid(),SIGINT);
}
sleep(1);
}
return 0;
}
给自己发送信号
int raise(int sig); 等价于kill(getpid(), sig);
发送闹铃信号
//信号处理函数
void func(int arg)
{
printf("闹钟触发:%d\n",arg);
time_t timep;
//获取时间
time(&timep);
//转换时间
printf("%s",ctime(&timep));
//解析时间显示到LCD设备中
alarm(1);//重新装置
}
int main()
{
//注册闹钟信号
signal(SIGALRM,func);
int i=0;
alarm(1); //1S发送一个闹钟信号
while(1)
{
;
}
return 0;
}