在man 2 write該NOTES部分包含以下注釋:
在 Linux 上,write()(和類似的系統呼叫)最多傳輸 0x7ffff000(2,147,479,552)個位元組,回傳實際傳輸的位元組數。(在 32 位和 64 位系統上都是如此。)
- 這是為什么?
- 該
DESCRIPTION路徑有以下一句:
根據 POSIX.1,如果 count 大于 SSIZE_MAX,則結果是實作定義的
SSIZE_MAX比0x7ffff000. 為什么會有這個筆記?
更新:感謝您的回答!如果有人感興趣(并且為了更好的 SEO 來幫助這里的開發人員),所有具有該限制的功能是:
readwritesendfile
要找到這一點,只需全文搜索手冊:
% man -wK "0x7ffff000"
/usr/share/man/man2/write.2.gz
/usr/share/man/man2/read.2.gz
/usr/share/man/man2/sendfile.2.gz
/usr/share/man/man2/sendfile.2.gz
uj5u.com熱心網友回復:
為什么會在這里?
我認為這不一定有充分的理由——我認為這基本上是一個歷史文物。讓我用一些 git 考古學來解釋一下。
在當前的 Linux 中,此限制受MAX_RW_COUNT以下約束:
ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
[...]
if (count > MAX_RW_COUNT)
count = MAX_RW_COUNT;
該常量被定義為整數最大值和頁面掩碼的 AND。這大致等于最大整數大小減去一頁的大小。
#define MAX_RW_COUNT (INT_MAX & PAGE_MASK)
所以這0x7ffff000就是來自 - 您的平臺具有 4096 位元組寬的頁面,即 2 12,因此它是未設定底部 12 位的最大整數值。
最后一次改變這一點的提交,忽略只是移動東西的提交,是 e28cc71572da3。
Author: Linus Torvalds <[email protected]>
Date: Wed Jan 4 16:20:40 2006 -0800
Relax the rw_verify_area() error checking.
In particular, allow over-large read- or write-requests to be downgraded
to a more reasonable range, rather than considering them outright errors.
We want to protect lower layers from (the sadly all too common) overflow
conditions, but prefer to do so by chopping the requests up, rather than
just refusing them outright.
所以,這給了我們一個改變的理由:為了防止整數溢位,寫入的大小被限制在接近最大整數的大小。大多數周圍的邏輯似乎已更改為使用 longs 或 size_t's,但檢查仍然存在。
在此更改之前,給它一個大于 INT_MAX 的緩沖區會導致 EINVAL 錯誤:
if (unlikely(count > INT_MAX))
goto Einval;
至于為什么要設定這個限制,它在 2.6.12 之前就存在了,這是第一個放入 git 的版本。我會讓比我更有耐心的人解決這個問題。:)
這是否符合 POSIX 標準?
戴上我的標準律師帽子,我認為這實際上是符合 POSIX 標準的。是的,POSIX 確實說寫入大于 SSIZE_MAX 是實作定義的行為,并且這不大于該限制。但是,我認為標準中還有另外兩個句子很重要:
write() 函式應嘗試將 nbyte 位元組從 buf 指向的緩沖區寫入與打開的檔案描述符 fildes 關聯的檔案。
[...]
成功完成后,write() 和 pwrite() 應回傳實際寫入與 fildes 關聯的檔案的位元組數。這個數字永遠不會大于 nbyte。否則,將回傳 -1 并設定 errno 以指示錯誤。
標準明確允許部分寫入。出于這個原因,所有呼叫 write() 的代碼都需要在一個回圈中包裝對 write() 的呼叫,該回圈重試短寫。
是否應該提高限額?
拋開歷史包袱和標準,今天有沒有理由提高這個限制?
我認為答案是否定的。write() 緩沖區的最佳大小是在嘗試避免內核和用戶空間之間過多的背景關系切換與確保您的資料盡可能適合快取之間的權衡。
coreutils 程式(提供 cat、cp 等)使用 128KiB 的緩沖區大小。硬體的最佳尺寸可能略大或略小。但是 2GB 緩沖區不太可能更快。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/382574.html
上一篇:如何繼續回圈遍歷GLfloat點
