原创作者: mryufeng   阅读:3027次   评论:0条   更新时间:2011-06-01    
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

结果如下:

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


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


看下源码红色部分:
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);
    if (! read_size) goto close;
    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 */
    }
close:
    efile_closefile((int) d->fd);

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的时候 不进行进一步读取.所以使用的时候请注意。


评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

文章信息

Global site tag (gtag.js) - Google Analytics