Linux下进程间管道通信

一.进程间通信概述:

进程间通信IPC(Interprocess Communication)是在Linux/UNIX下编程经常会碰到的问题,它的实际意义在于怎么样让多个进程可以互相的访问数据。在Linux/UNIX环境下可以由多种方式来实现上述的问题,

二. 进程间管道通信理解

一般来说,linux下的进程包含以下几个关键要素:

  • 有一段可执行程序;
  • 有专用的系统堆栈空间;
  • 内核中有它的控制块(进程控制块),描述进程所占用的资源,这样,进程才能接受内核的调度;
  • 具有独立的存储空间

linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。而对Unix发展做出重大贡献的两大主力AT&T的贝尔实 验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间通信方面的侧重点有所不同。前者对Unix早期的进程间通信手段进行了系统的改进和扩 充,形成了“system V IPC”,通信进程局限在单个计算机内;后者则跳过了该限制,形成了基于套接口(socket)的进程间通信机制。Linux则把两者继承了下来,如图 示:


其 中,最初Unix IPC包括:管道、FIFO、信号;System V IPC包括:System V消息队列、System V信号灯、System V共享内存区;Posix IPC包括: Posix消息队列、Posix信号灯、Posix共享内存区。有两点需要简单说明一下:1)由于Unix版本的多样性,电子电气工程协会(IEEE)开 发了一个独立的Unix标准,这个新的ANSI Unix标准被称为计算机环境的可移植性操作系统界面(PSOIX)。现有大部分Unix和流行版本都是遵循POSIX标准的,而Linux从一开始就遵 循POSIX标准;2)BSD并不是没有涉足单机内的进程间通信(socket本身就可以用于单机内的进程间通信)。事实上,很多Unix版本的单机 IPC留有BSD的痕迹,如4.4BSD支持的匿名内存映射、4.3+BSD对可靠信号语义的实现等等。

图一给出了 linux 所支持的各种IPC手段,在本文接下来的讨论中,为了避免概念上的混淆,在尽可能少提及Unix的各个版本的情况下,所有问题的讨论最终都会归结到 Linux环境下的进程间通信上来。并且,对于Linux所支持通信手段的不同实现版本(如对于共享内存来说,有Posix共享内存区以及System V共享内存区两个实现版本),将主要介绍Posix API。

linux下进程间通信的几种主要手段简介:

  1. 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
  2. 信 号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了 支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了 实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);
  3. 报文 (Message)队列(消息队列):消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字 节流以及缓冲区大小受限等缺点。
  4. 共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
  5. 信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
  6. 套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。

三. 进程间通信实例

1.linux下管道通信实例:

/*说明:一次作业,目的是了解Linux下进程和进程间通过管道通信
*         没考虑复杂算法和其他一些可能出现的问题
*功能:统计2个文本文件的字数和,2个参数分别为两文件名
*描述:父进程启动,开启子进程,子进程统计一个文本的字数,
*         待子进程结束,父进程统计另一个,在父进程中计算和打印统计结果
*/
#include < unistd . h
>
#include < stdio . h >
#include < stdlib . h >

int count ( FILE *);
int main ( int argc , char * argv [])
{
    
int num1 , num2 , totalnum ;     //文件1,文件2,中的字数和总字数
        
FILE * fpin1 ,* fpin2 ; //两个文件指针
        
if ( argc == 3 )
     {
        
fpin1 = fopen ( argv [ 1 ], "r" );
        
fpin2 = fopen ( argv [ 2 ], "r" );
     }
    
else if ( argc > 3 )
        
printf ( "Too many args!!/n" );
    
else
        
printf ( "Input a file two file names to count their total words!!/n" );

    
pid_t child ;
    
int status ;
    
int fds [ 2 ];
    
int buf1 [ 1 ], buf2 [ 1 ];
    
pipe ( fds );   //开启管道
        
if (( child = fork ())==- 1 )
     {
        
perror ( "fork" );
        
exit ( EXIT_FAILURE );
     }
    
else if ( child == 0 ) //子进程
        
{
        
close ( fds [ 0 ]);
        
buf1 [ 0 ]= count ( fpin1 );
        
write ( fds [ 1 ], buf1 , sizeof ( int ));     //结果写入管道
                
exit ( 1 );
     }
    
else //父进程
        
{
        
wait ( 0 );   //等待子进程结束
                
read ( fds [ 0 ], buf2 , sizeof ( int )); //从管道中读子进程返回结果
                
num1 = buf2 [ 0 ];
        
num2 = count ( fpin2 );
        
totalnum = num1 + num2 ;
        
printf ( "There are %d words in file1/n" , num1 );
        
printf ( "There are %d words in file2/n" , num2 );
        
printf ( "There are %d words in total/n" , totalnum );
        
exit ( 1 );
     }
    
//关闭文件
        
fclose ( fpin1 );
    
fclose ( fpin2 );
    
return 0 ;
}

//文件字数统计函数
int count ( FILE * fpin )
{
    
int num = 0 ;
    
char ch ;
    
int start = 0 ; //字是否开始
        
int end = 0 ;      //字是否结束
        
while (! feof ( fpin ))
     {
        
ch = getc ( fpin );
        
if (( ch >= 65 && ch <= 90 )||( ch >= 97 && ch <= 122 )) //字以字母开头
                        
start = 1 ;
        
if ( ch == 10 || ch == 13 || ch == 9 || ch == 32 )   //字以换行,回车,指标符,空格结束
                        
end = 1 ;
        
if ( start == 1 && end == 1 ) //字开始并结束了字数加1
                
{
            
num ++;
            
start = 0 ; //清0准备下一个统计
                        
end = 0 ;
         }
     }
    
return num ;
}

 

参考资料:

1。http://hi.baidu.com/yangxiang/blog/item/22a1a18b5a80ba7e9e2fb49d.html

2。http://www.ibm.com/developerworks/cn/linux/l-ipc/


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值