file:read_file的注意细节

arbow发现的问题如下:

4> file:read_file("/proc/cpuinfo").
{ok,<<>>}

11> {ok, IoDevice} = file:open("/proc/cpuinfo", [binary]),file:read(IoDevice, 1024).
{ok,<<"processor\t: 0\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 15\nmodel name\t: Intel(R) Core(TM)2 CPU "...>>}

同样的虚拟文件 不同的读法一个有内容 一个没有。

真实的文件就不存在这个问题。


erl -smp disable (禁止多smp的原因是容易找到pid)
strace -p PID

结果如下:

。。。。
[color=blue]stat("/proc/cpuinfo", {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
open("/proc/cpuinfo", O_RDONLY) = 7
close(7) = 0[/color]

[color=orange]stat("/proc/cpuinfo", {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
open("/proc/cpuinfo", O_RDONLY) = 7
poll([{fd=3, events=POLLIN|POLLRDNORM}, {fd=5, events=POLLIN|POLLRDNORM}, {fd=0, events=POLLIN|POLLRDNORM}], 3, 0) = 0
clock_gettime(CLOCK_MONOTONIC, {457571, 853399847}) = 0
read(7, "processor\t: 0\nvendor_id\t: Genuin"..., 8192) = 1238[/color]

看下源码红色部分:
static void invoke_read_file(void *data)
{
struct t_data *d = (struct t_data *) data;
size_t read_size;
int chop;

if (! d->c.read_file.binp) {
int fd;
int size;
if (! (d->result_ok =
efile_openfile(&d->errInfo, d->c.read_file.name,
EFILE_MODE_READ, &fd, &d->c.read_file.size))) {
goto done;
}
d->fd = fd;
size = (int) d->c.read_file.size;
if (size != d->c.read_file.size ||
! (d->c.read_file.binp = driver_alloc_binary(size))) {
d->result_ok = 0;
d->errInfo.posix_errno = ENOMEM;
goto close;
}
d->c.read_file.offset = 0;
}

read_size = (size_t) (d->c.read_file.size - d->c.read_file.offset);
[color=red] if (! read_size) goto close;[/color]
chop = d->again && read_size >= FILE_SEGMENT_READ*2;
if (chop) read_size = FILE_SEGMENT_READ;
d->result_ok =
efile_read(&d->errInfo,
EFILE_MODE_READ,
(int) d->fd,
d->c.read_file.binp->orig_bytes + d->c.read_file.offset,
read_size,
&read_size);
if (d->result_ok) {
d->c.read_file.offset += read_size;
if (chop) return; /* again */
}
[color=red] close:
efile_closefile((int) d->fd);[/color]
done:
d->again = 0;
}

static void invoke_read(void *data)
{
struct t_data *d = (struct t_data *) data;
int status, segment;
size_t size, read_size;

segment = d->again && d->c.read.bin_size >= 2*FILE_SEGMENT_READ;
if (segment) {
size = FILE_SEGMENT_READ;
} else {
size = d->c.read.bin_size;
}
read_size = size;
if (d->flags & EFILE_COMPRESSED) {
read_size = erts_gzread((gzFile)d->fd,
d->c.read.binp->orig_bytes + d->c.read.bin_offset,
size);
status = (read_size != -1);
if (!status) {
d->errInfo.posix_errno = EIO;
}
} else {
status = efile_read(&d->errInfo, d->flags, (int) d->fd,
d->c.read.binp->orig_bytes + d->c.read.bin_offset,
size,
&read_size);
}
if ( (d->result_ok = status)) {
ASSERT(read_size <= size);
d->c.read.bin_offset += read_size;
if (read_size < size || !segment) {
d->c.read.bin_size = 0;
d->again = 0;
} else {
d->c.read.bin_size -= read_size;
}
} else {
d->again = 0;
}
}


也就是说read_file 在发现文件长度为0的时候 [color=red]不进行进一步读取[/color].所以使用的时候请注意。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值