一,进程的通信:
种类:1.管道 2.信号 3.消息队列 4.共享内存 5.信号灯 6.套接字
1.管道:
1.无名管道
无名管道只能用于具有亲缘关系的进程间通信
pipe
int pipe(int pipefd[2]);
功能:
创建一个无名管道
参数:
pipefd[0]:读管道文件描述符
pipefd[1]:写管道文件描述符
返回值:
成功返回0
失败返回-1
eg:
int main(void)
{
pid_t pid;
int fd[2];
int ret = 0;
char tmpbuff[4096] = {0};
ret = pipe(fd); //创建无名管道,失败返回-1
if(ret == -1)
{
perror("fail to pipe");
return -1;
}
pid = fork();
if(pid == -1)
{
perror("fali to fork");
return -1;
}
if(pid == 0)
{
strcpy(tmpbuff,"hello world !");
write(fd[1],tmpbuff,strlen(tmpbuff)); //写入stelen长度的字符串,写用strlen,读用siezof
}else if(pid > 0)
{
read(fd[0],tmpbuff,sizeof(tmpbuff)); //read 具有阻塞功能(有写端的前提),在没有读到的时候会等待,但是系统不会等待,会去执行子程序,所以永远都是先子程序再父程序
printf("tmpbuff = :%s\n",tmpbuff); //sizeof是最多读4096大小的,但是有多少内容打印多少东西
}
close(fd[0]);
close(fd[1]);
return 0;
}
无名管道特性(16*4k):
1.管道中至少有一个写端:
读取数据时,如果管道中有数据直接读取,管道中没有数据阻塞等待直到有数据写入读出,继续向后执行
2.管道中没有写端:
读取数据时,如果管道中有数据直接读取,管道中没有数据不阻塞等待直接向下执行
3.管道中至少有一个读端:
写入数据时,如果管道中没有存满,则直接写入,管道中如果存满,则阻塞等待直到有数据读出,才能继续写入
4.管道中没有读端:
写入数据时,会产生管道破裂错误,导致程序崩溃
2.有名管道
打开管道文件 -> 读写管道文件 -> 关闭管道文件(文件IO)
注意:有名管道必须读写两端同时加入才能继续向下执行
1.mkfifo
int mkfifo(const char *pathname, mode_t mode);
功能:
创建一个管道文件
参数:
pathname:管道文件路径
mode:权限
返回值:
成功返回0
失败返回-1
memset(清零的数组首地址,0,sizeof(1参)) --- 数组置位为 0
eg:实现用两个管道对两个进程进行聊天的功能
文件A.c: 文件B.c:
2.信号
信号用来实现内核层和用户层信息的交互,也可以用来实现进程间通信
1.信号的种类
2.信号处理方式:
1.缺省:
按照系统默认的方式处理
2.忽略:
不响应信号
3.捕捉:
按照自定义方式处理信号
9号信号SIGKILL
19号信号SIGSTOP
这两个信号不能被忽略和捕捉
以下三个信号可以从键盘输入:
SIGINT:ctrl + c
SIGQUIT:ctrl + \
SIGTSTP:ctrl + z
4.signal
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
功能:
改变信号的处理方式
参数:
signum:信号的编号
handler:信号的处理方式
SIG_IGN 忽略处理
SIG_DFL 缺省处理
函数首地址 捕捉处理
返回值:
成功返回之前处理函数的首地址
失败返回SIG_ERR
eg:
void handler1(int signo)
{
printf("SIGINT 信号来了!\n");
}
void handler2(int signo)
{
printf("SIGQUIT 信号来了!\n");
}
void handler3(int signo)
{
printf("SIGTSTP号来了!\n");
}
int main(void)
{
signal(SIGINT,handler1);
signal(SIGQUIT,handler2);
signal(SIGTSTP,handler3);
while(1)
{
}
return 0;
}