linux 管道数据的写入hi_Linux进程间通信(1):管道

接上一篇的内容——Linux任务、进程和线程

参考书籍:《从实践中学嵌入式linux应用程序开发》(华清远见嵌入式学院)

Linux进程间通信:

1、同主机进程间数据交互机制:无名管道(PIPE)、有名管道(FIFO)、消息队列(Message Queue)和共享内存(Share Memory)。

2、同主机进程间同步机制:信号量(semaphore)。

3、同主机进程间异步机制:信号(Signal)。

4、网络主机间数据交互机制:套接字(Socket)

无名管道(pipe):

首先是 int pipe(int f[2]) 这个函数,其需要头文件,这个函数将创建一个未命名管道,并将管道的读端描述字包含在f[0]中,将写端描述字放在f[1]中,然后你就可以像利用普通文件描述字一样来读写数据了。

再次是int close(int fd) 函数, 其需要头文件,其用于关闭指定的文件描述字。

最后是write和read函数, 其需要头文件,用于读写数据。

无名管道的特点:

1、管道是半双工的,数据只能向一个方向流动,具有固定的读端和写端;需要双方通信时,需要建立起两个管道;

2、只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);

3、单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是单独构成一种文件系统,并且只存在与内存中。

4、数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

管道读写注意点:

只有在管道的读端存在时,向管道写入数据才有意义。否则向管道写入数据的进程将收到内核传来的SIGPIPE信号(通常为Broken pipe错误);

向管道写入数据时,Linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读取管道缓冲区中的数据,那么写操作将会一直阻塞;

父子进程在运行时,它们的先后顺序并不能保证。

/*pipe.c*/

#include #include#include#include

#define BUFF_SZ 256

intmain()

{

printf("app start...\n");

pid_t pid;int pipe_fd[2];charbuf[BUFF_SZ];const char data[] = "hi, this is the test data";intbytes_read;intbytes_write;//clear buffer, all bytes as 0

memset(buf, 0, sizeof(buf));//creat pipe

if(pipe(pipe_fd) < 0)//创建管道

{

printf("[ERROR] can not create pipe\n");

exit(1);

}//fork an new process

if(0 == (pid=fork()))//创建一个子进程

{//close the write-point of pipe in child process

close(pipe_fd[1]);//read bytes from read-point of pipe in child process

if((bytes_read = read(pipe_fd[0], buf, BUFF_SZ)) > 0)//子进程读取管道内容

{

printf("%d bytes read from pipe : '%s'\n", bytes_read, buf);

}//close read-point of pipe in child process

close(pipe_fd[0]);//关闭子进程读描述符

exit(0);

}//close read-point of pipe in parent process

close(pipe_fd[0]);//write bytes to write-point of pipe in parent process

if((bytes_write = write(pipe_fd[1], data, strlen(data))))

{

printf("%d bytes wrote to pipe : '%s'\n", bytes_write, data);

}//close write-point of pipe in parent process

close(pipe_fd[1]);//wait child process exit

waitpid(pid, NULL, 0);//收集子进程退出信息

printf("app end\n");return 0;

}

标准流管道:

标准流管道完成的工作:

创建一个管道;

fork()一个子进程;

在父子进程中关闭不需要的文件描述符;

执行exec()函数族调用;

执行函数中所调用的指令。

使用实例:

/*standard_pipe.c*/#include#include#include#include

#define BUFSIZE 1024

intmain()

{

FILE*fd;char *cmd = "ps -ef";charbuf[BUFSIZE];if((fd=popen(cmd,"r"))==NULL)//调用popen函数执行相应的命令

{

printf("popen fail\n");

exit(1);

}while((fgets(buf,BUFSIZE,fd)) !=NULL)

{

printf("%s",buf);

}

pclose(fd);//关闭流管道 exit(0);

}

有名管道(FIFO):

它可以使不相关的两个进程实现彼此通信;

该管道可以通过路径名来指出,并且在文件系统中是可见的。在建立了管道之后,两个进程就可以把它当作普通文件一样进行读写操作,使用非常方便;

FIFO严格地遵循先进先出规则,对管道及FIFO的读总是从开始处返回数据,对它们的写则是把数据添加到末尾,它们不支持如 lseek() 等文件操作。

函数 int mkfifo (char* path, mode_t mode) 负责创建FIFO管道,其需要头文件,参数path即要创建的管道文件存放位置,mode参数即文件权限。

更多的参考:http://pubs.opengroup.org/onlinepubs/009695399/functions/mkfifo.html。     FIFO管道创建完成以后,便可以使用open函数来打开它,然后进行读写操作了。

/*fifo_write.c*/#include#include#include#include#include#include#include#include

#define BUFFER_SIZE PIPE_BUF

#define FIFO_NAME "/tmp/my_fifo"

intmain()

{intpipe_fd;//if the pipe file do not exist

if (access(FIFO_NAME, F_OK) == -1)

{//creat FIFO pipe file

mkfifo(FIFO_NAME, 0777);

}//open FIFO pipe file.

pipe_fd =open(FIFO_NAME, O_WRONLY);//write data into pipe

write(pipe_fd, "hi, this is a test", PIPE_BUF);//close FIFO pipe file descriptor

close(pipe_fd);return 0;

}

/*fifo_read.c*/#include#include#include#include#include#include#include#include

#define FIFO_NAME "/tmp/my_fifo"

#define BUFFER_SIZE PIPE_BUF

intmain()

{intpipe_fd;char buffer[BUFFER_SIZE + 1];//reset all bytes in buffer as '\0'

memset(buffer, '\0', sizeof(buffer));//open FIFO pipe file.

pipe_fd =open(FIFO_NAME, O_RDONLY);if(read(pipe_fd, buffer, BUFFER_SIZE) > 0)

{

printf("data from FIFO : %s\n", buffer);

}//close pipe file descriptor

close(pipe_fd);return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值