linux无名管道和有名管道,RPC 第五课 有名管道与无名管道的定义及区别

进程之间的通讯,作为老牌的通讯方式:管道

管道分为: 无名管道和 有名管道

1、无名管道

popen 打开进程文件指针(单向管道)

pclose 关闭用popen打开的指向管道的指针

proc_open 打开一个用来输入和输出的文件指针(双向管道)

proc_close 管子资源文件

$desc=[

['pipe','r'],

['pipe','w'],

['file','/tmp/error.txt','a']

];

$cmd='cat';

$process=proc_open($cmd,$desc,$pipes);

if(!is_resource($process)){

exit('proc_open failure.');

}

fwrite($pipes[0],date('Y-m-d H:i:s'));

sleep(1);

echo 'daa';

$str=fread($pipes[1],100);

echo $str.PHP_EOL;

fclose($pipes[1]);

fclose($pipes[0]);

proc_close($process);

说明:$cmd =cat  直接打印数据

$desc=[

['pipe','r'],

['pipe','w'],

['file','/tmp/error.txt','a']

];

//$cmd='cat';

$cmd='php';

$process=proc_open($cmd,$desc,$pipes);

if(!is_resource($process)){

exit('proc_open failure.');

}

//fwrite($pipes[0],date('Y-m-d H:i:s'));

fwrite($pipes[0],'<?php  print_r($_SERVER); ?>');

/**fwrite($pipes[0],'<?php  echo time(); ?>');**/

fclose($pipes[0]);

//sleep(1);

//echo 'daa';

$str=stream_get_contents($pipes[1]);

echo $str.PHP_EOL;

fclose($pipes[1]);

proc_close($process);

这里的$cmd =php ,则说明要执行php文件Array

(

[HOSTNAME] => localhost.localdomain

[SELINUX_ROLE_REQUESTED] =>

[SHELL] => /bin/bash

[TERM] => xterm

[HISTSIZE] => 1000

[SSH_CLIENT] => 192.168.61.102 49385 22

[SELINUX_USE_CURRENT_RANGE] =>

[SSH_TTY] => /dev/pts/0

[USER] => root

[LS_COLORS] => rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:

[PATH] => /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/mysql5.6/bin:/usr/local/php/php7/bin:/root/bin

[MAIL] => /var/spool/mail/root

[_] => /usr/local/php/php7/bin/php

[PWD] => /home/song/php

[LANG] => en_US.UTF-8

[SELINUX_LEVEL_REQUESTED] =>

[HISTCONTROL] => ignoredups

[SSH_ASKPASS] => /usr/libexec/openssh/gnome-ssh-askpass

[HOME] => /root

[SHLVL] => 2

[LOGNAME] => root

[CVS_RSH] => ssh

[SSH_CONNECTION] => 192.168.61.102 49385 192.168.61.103 22

[LESSOPEN] => |/usr/bin/lesspipe.sh %s

[G_BROKEN_FILENAMES] => 1

[PHP_SELF] => Standard input code

[SCRIPT_NAME] => Standard input code

[SCRIPT_FILENAME] =>

[PATH_TRANSLATED] =>

[DOCUMENT_ROOT] =>

[REQUEST_TIME_FLOAT] => 1542807455.4841

[REQUEST_TIME] => 1542807455

[argv] => Array

(

[0] => Standard input code

)

[argc] => 1

)

2、有名管道

可以在两个独立的进程中独立通讯 。不再受制于父子进程,有名管道是一个文件,使用posix_mkfifo() 函数创建。这个函数有两个参数 第一个参数 文件路径(我们一般放在/tmp/目录下)第二个参数是maskmode 比如说 0644 、0755 这样的值。写数据、读数据  和我们操作普通文件是一样的。  fread($handle,100)  或 fgets($handle) 读取一行   fwrite($handle,$data)  使用fclose() 关闭资源

posix_mkfifo()

下面我们举个例子:

写入有名管道:pipe.php$file='/tmp/pipe';

if(!file_exists($file)){

posix_mkfifo($file,0644);

}

$handle=fopen($file,'w');

if(!$handle){

exit('create or open file failure.');

}

$count=0;

while($count<10){

fwrite($handle,$count."\n");

echo 'write '.$count.PHP_EOL;

sleep(1);

$count++;

}

fclose($handle);

unlink($file);

读有名管道:readpipe.php$file='/tmp/pipe';

if(!file_exists($file)){

exit("file not exists.\n");

}

$handle=fopen($file,'r');

while(true && !feof($handle)){

$str=trim(fgets($handle),PHP_EOL);

echo $str.PHP_EOL;

}

/*

while(true){

$str=trim(fgets($handle),PHP_EOL);

if(!empty($str)){

echo $str.PHP_EOL;

if($str=='exit'){

break;

}

}

}

*/

fclose($handle);

/**

在这里做一个说明,如果我想把有名管道的读取,做一个守护进程,应该怎么做?

我这里想在最外层 做一个 while(true)的循环,

判断文件是否存在,如果存在就执行任务,如果文件不存在,就在这里while循环着。

也不会退出程序。

**/

也可以直接使用linux的命令行:  cat /tmp/pipe  来读取。

做个提醒:

场景1

我们在命令行中 执行  php pipe.php   ,如果没有打开客户端读取,则写操作是一直处于阻塞的状态,直到有进程读取数据,才进行。

场景2

我们在命令行中 执行  php pipe.php   ,打开的客户端正在读取,突然间中断,则 发送方继续发送,直到发送完毕结束。

会造成数据丢失,就不能收到全部数据,这个怎么容错?

正常通讯的方式,是可以收取到所有的数据,但这程序也不排除有其他问题吧。

3、无名管道与有名管道的区别

1、无名管道:无文件,只能在两个相关的两个进程之间使用,且有相同的祖先进程才可通讯。

2、有名管道:系统中有可见的管道文件,不想管的进程也能交换数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值