2010-06-19 21 views
6

Theo trang người đàn ông để đọc (2), nó chỉ trả về 0 khi đạt đến EOF.Có thể đọc (2) trả về số không khi không ở EOF?

Tuy nhiên, Có vẻ như điều này không chính xác và đôi khi có thể trả lại bằng không, có lẽ vì tệp chưa sẵn sàng để đọc? Tôi có nên gọi select() để xem nó có sẵn sàng trước khi đọc một tập tin từ đĩa không?

Lưu ý rằng nbytes là: 1.445.888

Một số mẫu mã:

fd_set readFdSet; 
timeval timeOutTv; 

timeOutTv.tv_sec = 0; 
timeOutTv.tv_usec = 0; 

// Let's see if we'll block on the read. 
FD_ZERO(&readFdSet); 
FD_SET(fd, &readFdSet); 

int selectReturn = ::select(fd + 1, &readFdSet, NULL, NULL, &timeOutTv); 

if (selectReturn == 0) { 
    // There is still more to read. 
    return false; // But return early. 
} else if (selectReturn < 0) { 
    clog << "Error: select failure: " << strerror(errno) << endl; 
    abort(); 
} else { 
    assert(FD_ISSET(fd, &readFdSet)); 

    try { 
    const int bufferSizeAvailable = _bufferSize - _availableIn; 

    if (_availableIn) { 
     assert(_availableIn <= _bufferSize); 

     memmove(_buffer, _buffer + bufferSizeAvailable, _availableIn); 
    } 

    ssize_t got = ::read(fd, _buffer + _availableIn, bufferSizeAvailable); 

    clog << " available: " << bufferSizeAvailable << " availableIn: " 
     << _availableIn << " bufferSize: " << _bufferSize << " got " 
     << got << endl; 

    return got == 0; 
    } catch (Err &err) { 
    err.append("During load from file."); 
    throw; 
    } 
} 

Sản lượng đọc (khi nó không thành công với không có dữ liệu đọc):

available: 1445888 availableIn: 0 bufferSize: 1445888 got: 0 

này đang chạy trên centos4 32 bit như một máy ảo sử dụng VMware Server 1.0.10. Hệ thống tệp được đọc là cục bộ cho máy ảo. Máy chủ là Windows Server 2008 32 bit.

Các -a uname nói:

Linux q-centos4x32 2.6.9-89.0.25.ELsmp #1 SMP Thu May 6 12:28:03 EDT 2010 i686 i686 i386 GNU/Linux 

tôi nhận thấy rằng các liên kết http://opengroup.org/onlinepubs/007908775/xsh/read.html đưa ra dưới đây trạng thái:

The value returned may be less than nbyte if the number of bytes left in the file is less than nbyte, if the read() request was interrupted by a signal... 

If a read() is interrupted by a signal before it reads any data, it will return -1 with errno set to [EINTR]. 

If a read() is interrupted by a signal after it has successfully read some data, it will return the number of bytes read. 

Vì vậy, có lẽ tôi đang nhận được một tín hiệu gián đoạn đọc và do đó giá trị trả về là số không vì một lỗi hoặc nó nghĩ rằng không byte được đọc?

+0

Tôi không thể nghĩ tại sao nó sẽ trả về 0 khi không ở EOF. Bạn có thể cung cấp một ví dụ cụ thể về thời điểm điều này xảy ra không? –

+0

Nó xảy ra trong khoảng một trong 50.000 cố gắng giống nhau. – WilliamKF

+0

Không cần chọn() trên bộ mô tả tập tin. (Tại sao địa ngục trong thiên niên kỷ thứ 3 bạn vẫn sử dụng select() chứ không phải poll() ??) Các tập tin luôn có thể đọc được - chúng không phải là ổ cắm hoặc thiết bị, chúng không thể chặn.Thêm một chút thông tin về hệ thống - distro, phiên bản hạt nhân, hệ thống tệp được sử dụng - có thể hữu ích. – Dummy00001

Trả lời

1

Đã tìm ra! Tôi đã đọc bộ nhớ chưa được khởi tạo (UMR) và tìm kiếm không chính xác đến cuối tệp.

+0

'UMR' ​​là gì? – naive231

+0

Đó là một đọc từ bộ nhớ uninitialized - về cơ bản "ngẫu nhiên" giá trị. –

+0

@ naive231 UMR == Đọc bộ nhớ không khởi tạo. – WilliamKF

2

Trường hợp duy nhất khác mà tôi có thể nghĩ về read() trả về 0 là nếu bạn chuyển vào nbyte bằng 0; đôi khi điều đó có thể xảy ra nếu bạn đang đi qua kích thước của một cái gì đó hoặc khác như một tham số. Có thể đó là những gì đang xảy ra ngay bây giờ không?

Nếu tệp chưa sẵn sàng để đọc, điều gì sẽ xảy ra là trả về giá trị đọc -1 và errno được đặt thành EAGAIN.

+0

nbyte không bằng 0. – WilliamKF

+0

Tôi hiểu ... trong trường hợp đó, vấn đề có lẽ là một điều gì đó tinh tế đang xảy ra * xung quanh * cuộc gọi để đọc() thay vì cuộc gọi ... Tôi sẽ ngạc nhiên nếu một cuộc gọi hệ thống thông thường hóa ra là vi phạm một trong những điều kiện cơ bản của nó. Bạn có thể đăng thêm mã để xem liệu có điều gì đó phức tạp xảy ra xung quanh nó không? –

+0

Đã thêm mã mẫu. – WilliamKF

3

Sau một số nghiên cứu, thực tế có một số trường hợp mà theo đó nó sẽ trả về 0 mà bạn có thể không nghĩ là "EOF".

Đối với các chi tiết gritty, xem định nghĩa POSIX cho read(): http://opengroup.org/onlinepubs/007908775/xsh/read.html

Một số người đáng chú ý là nếu bạn hỏi nó để đọc 0 byte - kiểm tra lại rằng bạn không vô tình đi qua từ 0 đến nó - - và đọc qua phần cuối của phần "được viết" của tệp (bạn có thể thực sự tìm kiếm phần cuối của tệp, "mở rộng" tệp đó bằng số không nếu bạn viết ở đó, nhưng cho đến khi bạn thực hiện, "EOF" vẫn là ở cuối phần đã viết).

Dự đoán tốt nhất của tôi là bạn đang gặp phải sự cố thời gian ở đâu đó. Một số câu hỏi bạn cần hỏi là "Các tệp này được viết như thế nào?" và "Tôi có chắc là chúng không có chiều dài không khi tôi cố đọc chúng?" Đối với cái thứ hai, bạn có thể thử chạy một stat() trên tệp trước khi đọc nó để xem kích thước hiện tại của nó là gì.

+0

Tệp đã có trên đĩa và ổn định và chỉ được đọc, tệp dài 50k. Các nbyte không phải là số không và chúng tôi đang đọc từ đầu của tập tin. Gọi báo cáo stat() 50k. – WilliamKF

+4

@WilliamKF: Thật kỳ lạ. Nó chắc chắn âm thanh như nó có thể là một lỗi hạt nhân/hệ thống tập tin. Tôi thậm chí không chắc chắn cách tốt nhất để cô lập một trường hợp như thế này. Bạn có thể cần phải nhấn vào danh sách gửi thư linux-kernel hoặc kênh IRC. Một điều có thể đáng thử là xem liệu nó có xảy ra trên một loại hệ thống tập tin khác không. –

Các vấn đề liên quan