Windows平台下erlang的port进程关闭标准输入输出的方法

转载:http://arksea.iteye.com/blog/700032

 

为了避免与port进程的通信受一些printf调试信息的影响,通常都要关闭或者替换标准输入输出。 

Unix平台下,open_port只要指定nouse_stdio参数就可以让port进程使用fd 3、4作为通信信道, 

而在Windows平台下并没有所谓的3、4 fd可用,调用fdopen(3,“rb”)将会出错,这时可以使用 

dup和dup2手动进行替换,例子如下: 


port测试进程C代码

 

 

C代码    收藏代码
  1. #include "stdafx.h"  
  2. #include <stdio.h>  
  3. #include <iostream>  
  4. #include <io.h>  
  5. #include <fcntl.h>  
  6. #include <windows.h>  
  7.   
  8. int main(int argc, char* argv[])  
  9. {  
  10.     //复制stdio fd,之后我们将使用复制的句柄与Erlang通信  
  11.     FILE* f0 = fdopen(dup(0),"rb");  
  12.     FILE* f1 = fdopen(dup(1),"wb");  
  13.   
  14.     //Windows下默认为Text模式,按需要设置为BINARY模式,  
  15.     //否则\n将会被替换为\r\n,这通常不是我们想要的  
  16.     _setmode (_fileno(f0), _O_BINARY);  
  17.     _setmode (_fileno(f1), _O_BINARY);  
  18.   
  19.     //用一个临时文件替换stdio,并关闭之  
  20.     FILE* ftmp = tmpfile();  
  21.     dup2(fileno(ftmp), 0);  
  22.     dup2(fileno(ftmp), 1);  
  23.     fclose(stdin);  
  24.     fclose(stdout);  
  25.     fclose(ftmp);  
  26.     //测试一些输出  
  27.     fwrite("hello",1,5,f1);  
  28.     fputc(' ',f1);  
  29.     fflush(f1);  
  30.     printf("world");  
  31.     fflush(stdout);  
  32.     std::cout << "!!!!!\n";  
  33.     std::cout.flush();  
  34.     Sleep(5000);  
  35.   
  36.     return 0;  
  37. }  

 

 

 

测试用erlang代码:

 

 

Erlang代码    收藏代码
  1. -module(test).  
  2. -compile(export_all).  
  3.   
  4. start() ->  
  5.   P = open_port({spawn, "./Debug/teststdio.exe"},[binary]),  
  6.   loop(P).  
  7.     
  8. loop(P) ->  
  9.   receive  
  10.     {P, {data, Data}} ->  
  11.     io:format("~p~n",[Data]),  
  12.     loop(P)  
  13.   after 3000 ->  
  14.     timeout  
  15.   end.  

 

 

 

测试结果:

 

1、替换stdio后:

 

Erlang代码    收藏代码
  1. Eshell V5.7.5  (abort with ^G)  
  2. 1> c(test.erl).  
  3. {ok,test}  
  4. 2> test:start().  
  5. <<"hello ">>  
  6. timeout  
  7. 3>  

 

 

2、如果没有替换stdio,将会收到

 

Erlang代码    收藏代码
  1. test:start().  
  2. <<"hello ">>  
  3. <<"world">>  
  4. <<"!!!!!\r\n">>  
  5. timeout  

 

 

我们调用第三方库时很难确认是否会有stdio输出,这种方式很好的避免了printf信息对port通信的影响

 

 注意没有替换stdio部分的输出,stdin和stdout没有指定BINARY模式,\n被替换成\r\n了,

 再看看前面dup2部分的调用,虽然指定了"rb"和"wb",但这样是无效的,必须手动调用setmode进行设置才会有效

 

 最后说说windows下使用异步stdio的注意点,需要2个设置:

1、在open_port中指定overlapped_io参数

2、用_get_osfhandle函数得到替换后的io的HANDLE,以供ReadFile和WriteFile操作:

 

 

C代码    收藏代码
  1. HANDLE hin = (HANDLE)_get_osfhandle(_fileno(f0));  
  2. HANDLE hout= (HANDLE)_get_osfhandle(_fileno(f1));  

 

 

 在C程序里使用异步io虽然麻烦,但有时候却是必须的。比如windows系统下通过port访问串行口时,如果不使用overlapped模式,读取串口与读取stdio是不能同时进行的。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值