[英]Under what circumstances may c's write()-function write less data than requested?
我正在以大約10b至16000b的塊寫入文件,當時突然每個塊都被截斷為4050字節左右(具體來說是4050、4051和4074字節,按此順序)。 這意味着后續寫入將覆蓋本應寫入的數據,從而弄亂了我的數據。 4050b以下的任何塊都可以寫出。
不幸的是,我無法復制它。 我所擁有的只是混亂的文件,因此我正在調試以尋找可能導致此問題的東西。
對其進行調試,我意識到c的write()函數在后台被調用(這是Java代碼FileChannel.write(),但是標准庫調用c的write並僅檢查寫入的字節> 0),以及該文檔的文檔不保證它會寫出所有需要的數據,僅能告訴您寫了多少數據。
我不檢查用Java土地寫回的字節(但我確實知道,功能簽名幾乎完全相同),因此修復非常簡單。 但是,由於我無法重現此問題,因此我不知道已經解決了實際問題。 因此,因此我希望一些c專家可以告訴我我正在抽煙,或者在某些合理的情況下write()一次不能寫超過4050個字節。
它運行在64位Linux內核3.0.0-26版本上。
編輯:按照以下注釋展開:
我正在寫一個普通的文件系統文件。 我不確定在這種情況下非阻塞意味着什么,我沒有使用回調或任何東西,但是沒有明確告訴操作系統刷新每個塊。 使用Java的RandomAccessFile'rw'模式打開文件。
從man 2 write
:
The number of bytes written may be less than count if, for example,
there is insufficient space on the underlying physical medium, or the
RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)), or the
call was interrupted by a signal handler after having written less than
count bytes. (See also pipe(7).)
從man 2 setrlimit
:
RLIMIT_FSIZE
The maximum size of files that the process may create. Attempts
to extend a file beyond this limit result in delivery of a
SIGXFSZ signal. By default, this signal terminates a process,
but a process can catch this signal instead, in which case the
relevant system call (e.g., write(2), truncate(2)) fails with
the error EFBIG.
使用以下命令可以看到這些限制:
ulimit -Sf
ulimit -Hf
或通過使用此C程序:
#include <stdio.h>
#include <errno.h>
#include <sys/resource.h>
int main()
{
struct rlimit rl;
if (getrlimit(RLIMIT_FSIZE, &rl) == 0) {
printf("%d %d\n", rl.rlim_cur, rl.rlim_max);
} else {
fprintf(stderr, "error: %d\n", errno);
}
return 0;
}
從Linux程序員手冊的write(1)開始:“ write() 最多將字節數寫入文件...”
寫入多少取決於您要寫入的內容以及是否使用同步寫入。
例如,如果它是一個管道或一個套接字,則不能寫滿管道/套接字緩沖區已滿(在同步模式下:大於該緩沖區中可用的緩沖區)。
重現此問題的最簡單方法是讓用戶慢。 當您調用write()時,這將導致發送緩沖區幾乎已滿,這意味着並非您提供的所有數據都可以被寫入。 您可以減小發送和接收緩沖區的大小,以使此問題更加明顯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.