linux 管道通信
来源:互联网 发布:淘宝客分销系统源码 编辑:程序博客网 时间:2024/06/04 17:51
首先说明linux进程之间通信的主要方式。大型程序大多会涉及到某种形式的进程间通信,一个较大型的应用程序设计成可以相互通信的“碎片”,从而就把一个任务分到多个进程中去。进程间通信的方法有三种方式:
1, 管道(pipe)
2,System v IPC 机制 ,包括消息队列,信号量,共享内存
3,套接字(socket)
管道机制在UNIX开发的早期就已经提供了,它在本机上的两个进程间的数据传递表现的相当出色;套接字是在BSD(Berkeley Software Development)中出现的,现在的应用也相当的广泛;而System V IPC机制Unix System V 版本中出现的。
首先讲管道机制,会在以后把其他的通信机制都讲到。
管道分为pipe(无名管道)和FIFO(命名管道),它们都是通过内核缓冲区按先进先出的方式数据传输,管道一端顺序地写入数据,另一端顺序地读入数据读写的位置都是自动增加,数据只读一次,之后就被释放。1 ,PIPE无名管道
调用格式为int pipe(int filedes[2]);,文件描述符filedes[0]用来读数据,filedes[1]用来写数据。如果要求程序的可移植性好,就按照习惯的用法来编程。调用成功时,返回值为0;错误时,返回-1,并设置错误代码errno:
管道在用户程序看起来就像一个打开的文件,通过
read(filedes[0],void *_buf,size_t _nypes);
或者write
(filedes[1],void *_buf,size_t _nypes)
向这个文件读写数据其实是在读写内核缓冲区。下面给出实例:
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{
int pipedes[2];//pipe输入输出文件描述符
char s[13]="hello world!";
int pid;
if(pipe(pipedes)==-1)//创建管道失败
{
perror("pipe error!");
exit(EXIT_FAILURE);
}
if(pid=fork()<0)//创建子进程失败
{
perror("fork is error!\n");
return -1;
}
else if(pid==0)//在子进程中
{
printf("now,write data to pipe\n");
if(write(pipedes[1],s,13)==-1)
{
perror("write error!");
exit(EXIT_FAILURE);
}
else
{
printf("the written data is :%s\n",s);
exit(EXIT_SUCCESS);
}
}
else if(pid > 0)//在父进程中
{
sleep(4);//保证子进程写操作完成
printf("now read data from pipe!\n");
if(read(pipedes[0],s,13)==-1)
{
perror("read error!");
exit(EXIT_FAILURE);
}
printf("the data is %s\n",s);
}
return 0;
}
达到预期效果。
2,有名管道
无名管道时临时的,在完成通信后就自动消失,且只能在具有亲元关系的进程间实现通信。有名管道他是一个存在的特殊文件,可以在不同的进程间进行通信。用户可以使用shell来创建有名管道,也可以使用mkfifo函数来创建有名管道,可以使用read和write进行读写操作。
下面直接给出操作实例:
fifo_read.c
/** 管道通信:有名管道
* 无名管道只能用于具有亲缘关系的进程之间,而有名管道可以在互不相关的两个进程间
* 实现彼此通信。要注意,FIFO严格按照先进先出的规则,对管道及FIFO的读总是从开始
* 处返回数据,对它们的写则把数据添加到末尾,不支持lseek等文件定位操作。
*
* 有名管道的创建使用mkfifo()。创建成功后就可以使用open、read、write这些函数了。
* 读管道部分
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/*在这里设置打开管道文件的mode为只读形式*/
#define FIFOMODE (O_CREAT | O_RDWR | O_NONBLOCK)
#define OPENMODE (O_RDONLY | O_NONBLOCK)
#define FIFO_SERVER "myfifo"
int main(void)
{
char buf[100];
int fd;
int readnum;
/*创建有名管道,设置为可读写,无阻塞,如果不存在则按照指定权限创建*/
if ((mkfifo(FIFO_SERVER, FIFOMODE) < 0) && (errno != EEXIST)) {
printf("cannot create fifoserver\n");
exit(1);
}
printf("Preparing for reading bytes... ...\n");
/*打开有名管道,并设置非阻塞标志*/
if ((fd = open(FIFO_SERVER, OPENMODE)) < 0) {
perror("open");
exit(1);
}
while (1) {
/*初始化缓冲区*/
bzero(buf, sizeof(buf));
/*读取管道数据*/
if ((readnum = read(fd, buf, sizeof(buf))) < 0) {
if (errno == EAGAIN) {
printf("no data yet\n");
}
}
/*如果读到数据则打印出来,如果没有数据,则忽略*/
if (readnum != 0) {
buf[readnum] = '\0';
printf("read %s from FIFO_SERVER\n", buf);
}
sleep(1);
}
return 0;
}
fifo_write.c
#include <stdio.h>#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
/*特别注意写管道时,设置打开管道文件的格式必须为可写*/
#define FIFO_SERVER "myfifo"
#define OPENMODE (O_WRONLY | O_NONBLOCK)
int main(int argc, char **argv)
{
int fd;
int nwrite;
/*打开管道文件,可写非阻塞*/
if ((fd = open(FIFO_SERVER, OPENMODE)) < 0) {
perror("open");
exit(1);
}
/*如果没有在命令行中写入参数,那么要重新运行程序*/
if (argc == 1) {
printf("Please send something\n");
exit(1);
}
/*向管道文件中写入数据,在这里要用strlen,如果用sizeof,则只是4个字节的指针长度*/
if ((nwrite = write(fd, argv[1], strlen(argv[1]))) < 0) {
if (errno == EAGAIN) {
printf("The FIFO has not been read yet.Please try later\n");
}
}
else {
printf("write %s to FIFO\n", argv[1]);
}
return 0;
}
- Linux进程通信:管道
- Linux 管道通信
- Linux进程通信-管道
- Linux管道通信
- Linux管道通信
- linux 管道通信
- linux管道通信
- linux历程--管道通信
- Linux通信之管道
- Linux 管道通信 .
- linux管道通信
- linux下管道通信
- linux有名管道通信
- linux管道通信
- linux 进程通信 ----管道
- linux 管道通信
- linux 内核管道通信
- Linux管道通信
- SpringSrcureCode在grails中实现用户--角色--权限的管理
- ELF对线程局部储存的处理(1) __thread
- 匹配汉字的正则表达式
- mysql 导入数据
- 用Lucene索引数据库
- linux 管道通信
- iBatis动态SQL标签用法
- 关于UIView的userInteractionEnabled属性
- Heibernate 动态创建表
- TTL与COMS的区别
- Android学习笔记:设置日期和时间不能选择当前时刻以前的日期时间的解决办法升级版
- Mysql自动备份与恢复的脚本(windows)
- 关于m_pMainWnd = &dlg的错误
- Qt___QTextEdit____操作