linux 关闭连接 read,解决Linux下Erlang关闭port同时也关掉与其连接的C语言进程

经过上篇文章“linux下erlang关闭port同时也关掉与其连接的c语言进程”http://www.linuxidc.com/Linux/2013-11/92638.htm 的分析 ,我们澄清了erlang关闭端口时,stdin会得到一个feof,进而关闭stdin。经过进一步的探究,发现有另两种新的解决方法:

第一:借助于linux下read函数,read函数原型:

ssize_t read(int fd,void *buf,size_t count)

函数返回值分为下面几种情况:

1、如果读取成功,则返回实际读到的字节数。这里又有两种情况:一是如果在读完count要求字节之前已经到达文件的末尾,那么实际返回的字节数将小于count值,但是仍然大于0;二是在读完count要求字节之前,仍然没有到达文件的末尾,这是实际返回的字节数等于要求的count值。

2、如果读取时已经到达文件的末尾,则返回0。

3、如果出错,则返回-1。

因此,当erlang关闭端口时,read(0,buf,len)会返回0,此该让c进程退出。具体做法是

#include

#include

typedef unsigned char byte;

typedef char int8;

int main() {

FILE * fp;

fp = fopen("ports.log", "a+");

fprintf(fp, "start...\n");

fflush(fp);

byte buf[256]={0};

int i = 0;

for(;;)

{

int8 len = buf[0];

//方法1:利用feof时,read返回0

if ((i=read(0, buf, 3)) <= 0)

return (i);

write(1, buf, 3);

}

附:erlang的port_close()关闭时,read返回0并不是erlang进程向c进程发了0字节的东西,因为经过实验是无法向stdin中写0字节的东西, Port ! {self(), {command, “”}}c进程并没有挂掉,推导出read并没有返回0。

第二、借助于struct _IO_FILE结构体中的_flags字段,该字段的含义_flags:true表示stdin关闭;_flags:false表示stdin打开;

It's in /usr/include/libio.h (which is included in stdio.h) and struct defintion is:

struct _IO_FILE {

int _flags;          /* High-order word is _IO_MAGIC; rest is flags. */

#define _IO_file_flags _flags

/* The following pointers correspond to the C++ streambuf protocol. */

/* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */

char* _IO_read_ptr;  /* Current read pointer */

char* _IO_read_end;  /* End of get area. */

char* _IO_read_base;  /* Start of putback+get area. */

char* _IO_write_base; /* Start of put area. */

char* _IO_write_ptr;  /* Current put pointer. */

char* _IO_write_end;  /* End of put area. */

char* _IO_buf_base;  /* Start of reserve area. */

char* _IO_buf_end;    /* End of reserve area. */

/* The following fields are used to support backing up and undo. */

char *_IO_save_base; /* Pointer to start of non-current get area. */

char *_IO_backup_base;  /* Pointer to first valid character of backup area */

char *_IO_save_end; /* Pointer to end of non-current get area. */

struct _IO_marker *_markers;

struct _IO_FILE *_chain;

int _fileno;

#if 0

int _blksize;

#else

int _flags2;

#endif

_IO_off_t _old_offset; /* This used to be _offset but it's too small.  */

#define __HAVE_COLUMN /* temporary */

/* 1+column number of pbase(); 0 is unknown. */

unsigned short _cur_column;

signed char _vtable_offset;

char _shortbuf[1];

/*  char* _save_gptr;  char* _save_egptr; */

_IO_lock_t *_lock;

#ifdef _IO_USE_OLD_IO_FILE

};

具体方法是:

#include

#include

typedef unsigned char byte;

typedef char int8;

int8 read_exact(byte* buf, int8 len);

int8 write_exact(byte* buf, int8 len);

int main() {

FILE * fp;

fp = fopen("ports.log", "a+");

fprintf(fp, "start...\n");

fflush(fp);

byte buf[256]={0};

int i = 0;

for(;;)

{

int8 len = buf[0];

//方法2:利用feof时,置标志位_flags:true表示stdin关闭;_flags:false表示stdin打开;

read(0, buf, 3);

if(stdin->_flags)

{

fprintf(fp, "stdin closed by erlang\n");

return (i);

}

write(1, buf, 3);

}

为了验证性能:此时if(stdin->_flags)并不是一直在不停的判断,只是在port_close关闭stdin,对其置位时执行。此结论是通过反推得出的,具体实验如下:

将判断改为其反面,即stdin不关闭时写文件if(!stdin->_flags) fprintf(fp, "stdin closed by erlang\n");替换掉上面的if(stdin->_flags){fprintf(fp, "stdin closed by erlang\n");

return (i);}部分,结果发现在端口打开正常工作时,并没有发生写文件的动作;当改成if(stdin->_flags) fprintf(fp, "stdin closed by erlang\n");即置位后不退出,这样

当erlang关闭端口时_flags置位了,由c进程没有退出,此条件成立,故发生了循环写文件动作。结论:c进程对stdin的动作判断与erlang进程紧密相关,并不是单方面的情况,具体的执行时隙问题,留待以后进一步分析。

附:erl的测试程序如下:

-module(echo).

-export([start/0, stop/0, echo/1]).

start() ->

spawn(fun() ->

register(echo, self()),

process_flag(trap_exit, true),

Port = open_port({spawn, "./echo"}, []),

loop(Port)

end).

stop() ->

echo ! stop.

echo(Msg) ->

echo ! {call, self(), Msg},    %% Msg必须是一个List

receive

Result -> Result

after 1000 -> io:format("time out~n"), true

end.

loop(Port) ->

receive

{call, Caller, Msg} ->

Port ! {self(), {command, Msg}},    %% Msg必须是一个List

receive

{Port, {data, Data}} ->    %% 返回的Data也是一个List

Caller ! Data

end,

loop(Port);

stop ->

Port ! {self(), close},

receive

{Port, closed} -> exit(normal)

end;

{'EXIT', Port, Reason} ->

io:format("~p terminated !~n",[Port]),

exit({port_terminated, Reason})

end.0b1331709591d260c1c78e86d0c51c18.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值