【linux 文件】管道通信,信号通信
来源:互联网 发布:今日非农数据结果 编辑:程序博客网 时间:2024/06/04 18:41
LINUX使用的进程间通信放式:
1)无名管道(pipe)和有名管道(FIFO)
2)信号(signal)
3)消息队列
4)共享内存
5)信号量
6)套接字(socket)
一、管道通信
1、管道是单向的,先进先出的,它把一个进程的输出和另一个进程的输入连接在一起
2、一个进程(写进程)在管道的尾部写入数据,另一个进程(读数据)从管道的头部读出数据
无名管道:用于父子进程间的通信
有名管道:用于运行于同一系统中的任一两个进程间的通信
1.1无名通道的步骤:创建——读管道——写管道——关闭管道
Pipe函数
原型:int pipe(int filedes[2]);
参数:新建的两个描述符有filedes数组返回,filedes[0]表示管家的读取端,filedes[i]表示管道的写入端。
返回值:成功 0,失败-1
头文件:#include<unistd.h>
创建管道时要先创建子进程,子进程会继承父进程所有的管道
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
int pipe_fd[2];
pid_t pid;
int r_num;
char buf_r[100];
char *p_wbuf;
memset(buf_r,0,sizeof(buf_r));
if(pipe(pipe_fd)<0) //创建子程序
{
printf("pipe creat error\n");
return -1;
}
if((pid = fork())==0)//进入子进程
{
printf("\n");
// close(pipe_fd[1]);
sleep(2);
if((r_num = read(pipe_fd[0],buf_r,100))>0)//进入父进程
{
printf("%d numbers read from the pipe is %s\n",r_num,buf_r);
}
if(write(pipe_fd[1],"HELLO WORLD",12)!= -1)
{
printf("son write3 pipe!\n");
}
close(pipe_fd[0]);
exit(0);
}
else
{
if(pid >0)
{
close(pipe_fd[0]);
if(write(pipe_fd[1],"HEllO",5)!=-1)
{
printf("parent write1 HELLO\n");
}
if(write(pipe_fd[1],"pipe",5)!=-1)
{
printf("parent write2 pipe!\n");
}
sleep(3)
close(pipe_fd[1;
sleep(3);
waitpid(pid,NULL,0);
exit(0);
}
}
return 0;
}
管道是单向的性质决定了在父子进程两端不可以做双向通信。
进程试图读空进程,进程将阻塞;管道已满时,进程在试图向管道内写入数据的时候,也会阻塞
1.2有名管道
任意两个进程之间:
创建——删除——打开——关闭——读——写
2、mififo函数
作用:创建有名管道
原型:int mkfifo (const char *filename,made_t mode)
参数:filename :有名管道路径,名称
Mode 管道方式
1)O_NONBLOCK FIFO打开时会立刻返回,非阻塞
2)O_RDONLY 只读
3)O_WRONLY 只写
4)O_RDWR 可读写
返回值:成功 为0;失败为-1,错误的原因存于errno
读程序:
#include<fcntl.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdlib.h>
#include<errno.h>
#define FIFO "/tmp/myfifo"
int main(int argc,char ** argv)
{
char buf_r[100];
int fd;
int nread;
/*创建管道*/
if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno != EEXIST))
{
printf("cannot creat fifoserver\n");
}
printf("Preparing for reading bytes...\n");
memset(buf_r,0,sizeof(buf_r));
/*打开管道*/
fd = open(FIFO,O_RDONLY|O_NONBLOCK,0);
if(fd == -1)
{
perror("open");
exit(1);
}
while(1)
{
memset(buf_r,0,sizeof(buf_r));
if((nread = read(fd,buf_r,100))==-1)
{
if(errno == EAGAIN)
{
printf("no day yet\n");
}
}
printf("read %s from FIFO\n",buf_r);
sleep(1);
}
pause();
unlink(FIFO);
}
写程序:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>
#define FIFO_SERVER "/tmp/myfifo"
int main(int argc,char**argv)
{
int fd;
char w_buf[100];
int nwrite;
int pipe_fd[2];
pid_t pid;
/*打开管道*/
fd = open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);
if(argc == 1)
{
printf("Please send somethong\n");
exit(-1);
}
if(pipe(pipe_fd)<0)
{
printf("pipe error!\n");
}
strcpy(w_buf,argv[1]);
/*向管道中写数据*/
if((nwrite = write(fd,w_buf,100)) == -1 )
{
if(errno == EAGAIN)
{
printf("the fifo has not been read yet.please try again\n");
}
else
{
printf("write %s to the fifo\n",w_buf);
}
}
}
注意:以上两个程序在执行的时候,要同时打开两个终端,先打开读程序执行创建管道,在打开写程序执行。否则,管道阻塞,写的内容不会保存在管道中。
二、信号通信
常见信号
SIGHUP: 从终端上发出的结束信号
SIGINT: 来自键盘的中断信号(Ctrl-C)
SIGKILL:该信号结束接收信号的进程,杀死进程
SIGTERM:kill命令发出的信号
SIGCHLD:子进程停止或结束时通知父进程
SIGSTOP:来自键盘(Ctrl-Z)或调试程序的停止执行信号,暂停进程
当某信号出现时,将按照下列三种方式中的一种进行处理:
1、忽略此信号
大多数信号都按照这种方式进行处理,但有两种信号
决不能被忽略,它们是:
SIGKILL\SIGSTOP。
这两种信号不能被忽略的原因是:它们向超级用户提供了一种终止或停止进程的方法
2、执行用户希望的动作
通知内核在某种信号发生时,调用一个用户函数。在用户函数中,执行用户希望的处理
3、执行系统默认动作
对大多数信号的系统默认动作是终止该进程
2.1 kill函数
作用:传送信号给指定的进程
原型:int kill (pid_t pid,int sig)
参数:pid : >0 指定的进程PID
=0 发送给目前进程相同进程组的所有进程
=-1 广播给系统内所有的进程
< 0 将信号发送给其进程组ID等于pid绝对值的进程。
2.2 raise函数
功能:发送信号给自身
原型:int raise (int sig)
头文件:#include <signal.h>
2.3 alarm函数
作用:设置信号传送给信号
原型: unsigned int alarm (unsigned int seconds)
返回值:返回之前闹钟的剩余秒数,若没有设置闹钟,返回0
头文件:#include <signal.h>
2.4 pause函数
作用:让进程暂停,直到信号被中断
原型:int pause(void)
返回值:-1
2.5 signal
作用:设置信号方式
原型:void (*signal(int signum,void(*handler)(int)))(int);
例程:
#include<stdio.h>
#include<signal.h>
void my_func(int sign_no)
{
if(sign_no == SIGINT)
{
printf("I have a signal SIGINT\n");
}
if(sign_no == SIGQUIT)
{
printf("I have a signal SIGOUT\n");
}
}
int main()
{
printf("waiting for signal SIGINT or SIGOUT\n");
signal(SIGINT,my_func);
signal(SIGQUIT,my_func);
pause();
exit(0);
}
- 【linux 文件】管道通信,信号通信
- linux进程的信号通信与进程的管道通信
- linux 进程间通信一(管道与信号)
- linux下c编程进程通信-管道与信号
- Linux进程间通信编程(一)管道和信号
- linux-基础-进程通讯(一)-管道通信/信号/内存共享
- Linux进程通信:管道
- Linux 管道通信
- Linux进程通信-管道
- Linux管道通信
- Linux管道通信
- linux 管道通信
- linux管道通信
- linux历程--管道通信
- Linux通信之管道
- Linux 管道通信 .
- linux管道通信
- linux下管道通信
- a
- 【HDU 3887】【dfs序+线段树】Counting Offspring 【查询子树上标号比它小的点有多少个 】
- Django笔记 数据库数据外键 多对多关系访问
- 函数的可重入性理解
- HTTP 请求头与请求体
- 【linux 文件】管道通信,信号通信
- 业余03—MicrosoftOffice激活工具
- android addCategory()等说明
- uboot 分析之 配置+编译过程
- 详解梯度下降法求解线性模型参数
- WCF:并发1
- nyoj组合数
- Spring Boot 之 Consuming a RESTful Web Service
- java web(1)