目的
数据传输——一个进程需要将它的数据发送给另一个进程
资源共享——多个进程之间共享同样的资源
通知事件——一个进程需要向另一个或一组进程发送消息,通知它们发生了某种事件
进程控制——有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有操作,并能够及时知道它的状态改变
分类
现在Linux使用的进程间通信方式包括:
1、无名管道(pipe)和有名管道(FIFO)
2、信号(signal)
3、消息队列
4、共享内存
5、信号量
6、套接字(socket)
管道通信
·管道是单向的、先进先出的,它把一个进程的输出和另一个进程的输入连接在一起。
·一个进程(写进程)在管道的尾部写入数据,另一个进程(读进程)从管道的头部读出数据
·数据被一个进程读出后,将被从管道中删除,其它读进程将不能再读到这些数据。
·管道提供了简单的流控制机制,进程试图读空管道时,进程将阻塞。同样,管道已经满时,进程再试图向管道写入数据,进程将阻塞
无名管道:
1.pipe
函数的原型:int pipe(int fds[2])
函数的参数:新建的两个描述符fds数组返回,fds[0]表示管道的读取端,fds[1]表示管道的写入端。
返 回 值:成功0,出错-1
头 文 件:#include <unistd.h>
管道读写:
1.先创建管道pipe;
2.fork创建子进程
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int pipe_fd[2];
if(pipe(pipe_fd)<0)
{
printf("pipe create error\n");
return -1;
}
else
printf("pipe create success\n");
close(pipe_fd[0]);
close(pipe_fd[1]);
}
有名管道:
·创建管道mkfifo
·打开管道open
·读管道read
·写管道write
·关闭管道close
·删除管道unlink
2.mkfifo
函数的作用:创建有名管道
函数的原型:int mkfifo(const char * filename,mode_t mode)
参数的作用:filename:有名管道的路径、名称
mode:打开管道的方式
O_NONBLOCK: FIFO打开的时候,费阻塞
O_RDONLY: 只读
O_WRONLY: 只写
O_RDWR: 可读写
返 回 值:成功 0 出错 -1
信号通信
方式:
信号类型:
下面是几种常见的信号:
§ SIGHUP: 从终端上发出的结束信号
§ SIGINT: 来自键盘的中断信号(Ctrl-C)
§ SIGKILL:该信号结束接收信号的进程,杀死进程
§ SIGTERM:kill 命令发出的信号
§ SIGCHLD:子进程停止或结束时通知父进程
§ SIGSTOP:来自键盘(Ctrl-Z)或调试程序的停止执行信号,暂停进程
3.kill
函数的作用:传送信号给指定的进程
函数的原型:int kill(pid_t pid,int sig)
函数的参数:pid > 0 指定的进程的PID
pid = 0 发送给目前进程相同组的所有进程
pid = -1 广播给系统内所有的进程
pid < 0
sig : 信号
返 回 值:成功 0 出错 -1
头 文 件:#include <signal.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
int ret;
if((pid=fork()) < 0)
{
perror("fork");
exit(1);
}
if(pid == 0)
{
raise(SIGSTOP);
exit(0);
}
else
{
printf("pid=%d\n", pid);
if((waitpid(pid, NULL, WNOHANG)) == 0)
{
kill(pid,SIGKILL);
printf("kill %d\n", pid);
}
else
{
perror("kill");
}
}
}
4.raise
函数的作用:发送信号给自身
函数的原型:int raise(int sig)
头 文 件:#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
int main()
{
pid_t pid;
int ret;
if((pid= fork()) < 0)
{
printf("Fork error.\n");
exit(-1);
}
if(pid == 0)
{
printf("child (pid:%d) is waiting for any signal\n.", getpid());
raise(SIGSTOP);
exit(0);
}
else
{
if((waitpid(pid, NULL, WNOHANG)) == 0)
{
kill(pid, SIGKILL);
printf("parent kill child process %d\n", pid);
}
waitpid(pid, NULL, 0);
exit(0);
}
}
5.alarm
函数的作用:设置信号传送闹钟
函数的原型:unsigned int alarm(unsigned int seconds)
返 回 值:返回之前闹钟的剩余秒数,如果之前未设闹钟则返回0
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
void handle()
{
printf(“hello!\n”);
}
int main()
{
int i;
signal(SIGALRM,handle);
alarm(5);
for(i = 0; i <= 7; i++)
{
printf(“sleeping...%d\n”,i);
sleep(1);
}
}
6.pause
函数的作用:让进程暂停,直到信号的出现
函数的原型:int pause(void);
返 回 值:-1
头 文 件:#include <unistd.h>
7.signal
函数的作用:设置信号处理方式
函数的原型:void (* signal(int signum,void(*handler)(int))(int)
typedef void(*sighandler_t)(int)
sighandler_t signal(int signum,sighandler_t handler);