splice 和管道¶
splice API¶
splice 是一種在核心內部移動資料塊的方法,而無需在核心和使用者空間之間不斷傳輸它們。
-
ssize_t splice_to_pipe(struct pipe_inode_info *pipe, struct splice_pipe_desc *spd)¶
將傳遞的資料填充到管道中
引數
struct pipe_inode_info *pipe要填充的管道
struct splice_pipe_desc *spd要填充的資料
描述
spd 包含頁面和 len/offset 元組的對映,以及與這些頁面關聯的 struct pipe_buf_operations。此函式會將該資料鏈接到管道。
-
ssize_t copy_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags)¶
從檔案複製資料並將副本拼接到管道中
引數
struct file *in要從中讀取的檔案
loff_t *ppos指向要從中讀取的檔案位置的指標
struct pipe_inode_info *pipe要拼接到的管道
size_t len要拼接的數量
unsigned int flagsSPLICE_F_* 標誌
描述
此函式分配足夠容納所請求資料量(但受剩餘管道容量限制)的頁面,將其傳遞給檔案的 ->read_iter() 以讀取到其中,然後將已使用的頁面拼接到管道中。
返回
成功時,將返回讀取的位元組數,如果適用,將更新 *ppos;如果沒有更多資料要讀取,將返回 0;如果管道沒有空間,將返回 -EAGAIN,如果發生錯誤,將返回其他負錯誤程式碼。如果管道空間不足、到達資料末尾或遇到空洞,則可能發生短讀取。
-
int splice_from_pipe_feed(struct pipe_inode_info *pipe, struct splice_desc *sd, splice_actor *actor)¶
將管道中的可用資料饋送到檔案
引數
struct pipe_inode_info *pipe要從中拼接的管道
struct splice_desc *sd傳遞給 actor 的資訊
splice_actor *actor拼接資料的處理程式
描述
此函式迴圈遍歷管道並呼叫 actor 來執行將單個
struct pipe_buffer移動到目標位置的實際操作。當管道中沒有更多緩衝區時,或者當請求的位元組數(sd->total_len)已被複制時,它會返回。如果管道需要填充更多資料,它會返回一個正數(一);如果所需的位元組數已被複制,則返回零;如果發生錯誤,則返回 -errno。此函式與 splice_from_pipe_{begin,end,next} 一起,可用於實現
__splice_from_pipe()的功能,當需要在將管道緩衝區複製到目標位置時進行鎖定。
-
int splice_from_pipe_next(struct pipe_inode_info *pipe, struct splice_desc *sd)¶
等待一些資料進行拼接
引數
struct pipe_inode_info *pipe要從中拼接的管道
struct splice_desc *sd有關拼接操作的資訊
描述
此函式將等待一些資料,如果管道緩衝區可用,則返回一個正值(一)。如果沒有更多資料需要拼接,它將返回零或 -errno。
-
void splice_from_pipe_begin(struct splice_desc *sd)¶
開始從管道拼接
引數
struct splice_desc *sd有關拼接操作的資訊
描述
應在包含
splice_from_pipe_next()和splice_from_pipe_feed()的迴圈之前呼叫此函式,以初始化 sd 的必要欄位。
-
void splice_from_pipe_end(struct pipe_inode_info *pipe, struct splice_desc *sd)¶
完成從管道拼接
引數
struct pipe_inode_info *pipe要從中拼接的管道
struct splice_desc *sd有關拼接操作的資訊
描述
如有必要,此函式將喚醒管道寫入器。應在包含
splice_from_pipe_next()和splice_from_pipe_feed()的迴圈之後呼叫此函式。
-
ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd, splice_actor *actor)¶
將管道中的資料拼接到給定的 actor
引數
struct pipe_inode_info *pipe要從中拼接的管道
struct splice_desc *sd傳遞給 actor 的資訊
splice_actor *actor拼接資料的處理程式
描述
此函式的功能僅限於迴圈遍歷管道並呼叫 actor 來執行將單個
struct pipe_buffer移動到目標位置的實際操作。請參閱 pipe_to_file、pipe_to_sendmsg 或 pipe_to_user。
-
ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags, splice_actor *actor)¶
將管道中的資料拼接到檔案
引數
struct pipe_inode_info *pipe要從中拼接的管道
struct file *out要拼接到的檔案
loff_t *pposout 中的位置
size_t len要拼接的位元組數
unsigned int flags拼接修飾符標誌
splice_actor *actor拼接資料的處理程式
描述
請參閱 __splice_from_pipe。此函式鎖定管道 inode,否則它與
__splice_from_pipe()相同。
-
ssize_t iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags)¶
將管道中的資料拼接到檔案
引數
struct pipe_inode_info *pipe管道資訊
struct file *out要寫入的檔案
loff_t *pposout 中的位置
size_t len要拼接的位元組數
unsigned int flags拼接修飾符標誌
描述
將從給定的管道 inode 移動或複製頁面(由 flags 選項確定)到給定的檔案。這一個基於 ->write_iter。
-
ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags)¶
將管道中的資料拼接到套接字
引數
struct pipe_inode_info *pipe要從中拼接的管道
struct file *out要寫入的套接字
loff_t *pposout 中的位置
size_t len要拼接的位元組數
unsigned int flags拼接修飾符標誌
描述
將從管道傳送 len 位元組到網路套接字。不涉及資料複製。
-
ssize_t vfs_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags)¶
從檔案讀取資料並將其拼接到管道中
引數
struct file *in要從中拼接的檔案
loff_t *ppos輸入檔案偏移量
struct pipe_inode_info *pipe要拼接到的管道
size_t len要拼接的位元組數
unsigned int flags拼接修飾符標誌 (SPLICE_F_*)
描述
將請求的資料量從輸入檔案拼接到管道。這是同步的,因為呼叫者必須在整個操作過程中持有管道鎖。
如果成功,它將返回拼接的資料量;如果它遇到 EOF 或空洞,則返回 0;否則返回一個負錯誤程式碼。
-
ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, splice_direct_actor *actor)¶
在兩個非管道之間直接拼接資料
引數
struct file *in要從中拼接的檔案
struct splice_desc *sd關於拼接位置的 actor 資訊
splice_direct_actor *actor處理資料拼接
描述
這是一個特殊情況的輔助函式,用於直接在兩個點之間拼接,而無需顯式管道。在內部,分配的管道快取在程序中,並在該程序的生命週期內重複使用。
-
ssize_t do_splice_direct(struct file *in, loff_t *ppos, struct file *out, loff_t *opos, size_t len, unsigned int flags)¶
在兩個檔案之間直接拼接資料
引數
struct file *in要從中拼接的檔案
loff_t *ppos輸入檔案偏移量
struct file *out要拼接到的檔案
loff_t *opos輸出檔案偏移量
size_t len要拼接的位元組數
unsigned int flags拼接修飾符標誌
描述
供 do_sendfile() 使用。splice 可以輕鬆地模擬 sendfile,但在應用程式中執行它會產生額外的系統呼叫(splice in + splice out,與僅 sendfile() 相比)。因此,此輔助函式可以直接透過程序私有管道進行拼接。
呼叫者已經對整個範圍呼叫了 rw_verify_area()。
-
ssize_t splice_file_range(struct file *in, loff_t *ppos, struct file *out, loff_t *opos, size_t len)¶
在兩個檔案之間拼接資料以用於 copy_file_range()
引數
struct file *in要從中拼接的檔案
loff_t *ppos輸入檔案偏移量
struct file *out要拼接到的檔案
loff_t *opos輸出檔案偏移量
size_t len要拼接的位元組數
描述
供 ->copy_file_range() 方法使用。與
do_splice_direct()類似,但 vfs_copy_file_range() 已經在 out 檔案上持有 start_file_write()。
呼叫者已經對整個範圍呼叫了 rw_verify_area()。
管道 API¶
管道介面全部供核心內部(內建映象)使用。它們不匯出供模組使用。
-
struct pipe_buffer¶
Linux 核心管道緩衝區
定義:
struct pipe_buffer {
struct page *page;
unsigned int offset, len;
const struct pipe_buf_operations *ops;
unsigned int flags;
unsigned long private;
};
成員
page包含管道緩衝區資料的頁面
offsetpage 中資料的偏移量
lenpage 中資料的長度
ops與此緩衝區關聯的操作。請參閱 pipe_buf_operations。
flags管道緩衝區標誌。請參閱上文。
privateops 擁有的私有資料。
-
struct pipe_inode_info¶
Linux 核心管道
定義:
struct pipe_inode_info {
struct mutex mutex;
wait_queue_head_t rd_wait, wr_wait;
union {
unsigned long head_tail;
struct {
pipe_index_t head;
pipe_index_t tail;
};
};
unsigned int max_usage;
unsigned int ring_size;
unsigned int nr_accounted;
unsigned int readers;
unsigned int writers;
unsigned int files;
unsigned int r_counter;
unsigned int w_counter;
bool poll_usage;
#ifdef CONFIG_WATCH_QUEUE;
bool note_loss;
#endif;
struct page *tmp_page[2];
struct fasync_struct *fasync_readers;
struct fasync_struct *fasync_writers;
struct pipe_buffer *bufs;
struct user_struct *user;
#ifdef CONFIG_WATCH_QUEUE;
struct watch_queue *watch_queue;
#endif;
};
成員
mutex保護整個物件的互斥鎖
rd_wait空管道情況下讀取器等待點
wr_wait滿管道情況下寫入器等待點
{unnamed_union}anonymous
head_tailhead 和 tail 的 unsigned long 聯合
{unnamed_struct}anonymous
head緩衝區生產點
tail緩衝區消費點
max_usage環中可能使用的最大槽數
ring_size緩衝區總數(應為 2 的冪)
nr_accounted此管道在 user->pipe_bufs 中佔用的數量
readers此管道的當前讀取器數量
writers此管道的當前寫入器數量
files引用此管道的
struct file數量(受 ->i_lock 保護)r_counter讀取器計數器
w_counter寫入器計數器
poll_usage此管道是否用於 epoll,它具有瘋狂的喚醒?
note_loss下一個 read() 應插入資料丟失訊息
tmp_page快取的已釋放頁面
fasync_readers讀取器側 fasync
fasync_writers寫入器側 fasync
bufs管道緩衝區的迴圈陣列
user建立此管道的使用者
watch_queue如果此管道是 watch_queue,則這是相關內容
-
bool pipe_has_watch_queue(const struct pipe_inode_info *pipe)¶
檢查管道是否為 watch_queue,即是否使用 O_NOTIFICATION_PIPE 建立
引數
const struct pipe_inode_info *pipe要檢查的管道
返回
如果管道是 watch 佇列,則為 true;否則為 false。
-
unsigned int pipe_occupancy(unsigned int head, unsigned int tail)¶
返回管道中使用的槽數
引數
unsigned int head管道環頭指標
unsigned int tail管道環尾指標
-
bool pipe_empty(unsigned int head, unsigned int tail)¶
如果管道為空,則返回 true
引數
unsigned int head管道環頭指標
unsigned int tail管道環尾指標
-
bool pipe_full(unsigned int head, unsigned int tail, unsigned int limit)¶
如果管道已滿,則返回 true
引數
unsigned int head管道環頭指標
unsigned int tail管道環尾指標
unsigned int limit可用槽位的最大數量。
-
bool pipe_is_full(const struct pipe_inode_info *pipe)¶
如果管道已滿,則返回 true
引數
const struct pipe_inode_info *pipe管道
-
bool pipe_is_empty(const struct pipe_inode_info *pipe)¶
如果管道為空,則返回 true
引數
const struct pipe_inode_info *pipe管道
-
unsigned int pipe_buf_usage(const struct pipe_inode_info *pipe)¶
返回正在使用的管道緩衝區數量
引數
const struct pipe_inode_info *pipe管道
-
struct pipe_buffer *pipe_buf(const struct pipe_inode_info *pipe, unsigned int slot)¶
返回管道環中指定槽位的管道緩衝區
引數
const struct pipe_inode_info *pipe要訪問的管道
unsigned int slot感興趣的槽位
-
struct pipe_buffer *pipe_head_buf(const struct pipe_inode_info *pipe)¶
返回管道環頭部的管道緩衝區
引數
const struct pipe_inode_info *pipe要訪問的管道
-
bool pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)¶
獲取對 pipe_buffer 的引用
引數
struct pipe_inode_info *pipe緩衝區所屬的管道
struct pipe_buffer *buf要獲取引用的緩衝區
返回
如果成功獲取引用,則為 true。
-
void pipe_buf_release(struct pipe_inode_info *pipe, struct pipe_buffer *buf)¶
釋放一個 pipe_buffer 的引用
引數
struct pipe_inode_info *pipe緩衝區所屬的管道
struct pipe_buffer *buf要釋放引用的緩衝區
-
int pipe_buf_confirm(struct pipe_inode_info *pipe, struct pipe_buffer *buf)¶
驗證管道緩衝區的內容
引數
struct pipe_inode_info *pipe緩衝區所屬的管道
struct pipe_buffer *buf要確認的緩衝區
-
bool pipe_buf_try_steal(struct pipe_inode_info *pipe, struct pipe_buffer *buf)¶
嘗試獲取 pipe_buffer 的所有權
引數
struct pipe_inode_info *pipe緩衝區所屬的管道
struct pipe_buffer *buf嘗試竊取的緩衝區
-
bool generic_pipe_buf_try_steal(struct pipe_inode_info *pipe, struct pipe_buffer *buf)¶
嘗試獲取
pipe_buffer的所有權
引數
struct pipe_inode_info *pipe緩衝區所屬的管道
struct pipe_buffer *buf嘗試竊取的緩衝區
描述
此函式嘗試竊取附加到 buf 的
struct page。如果成功,此函式返回 0 並在頁面鎖定的情況下返回。呼叫者可以將其重新用於任何他希望的目的;典型用途是插入到不同的檔案頁快取中。
-
bool generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)¶
獲取對
struct pipe_buffer的引用
引數
struct pipe_inode_info *pipe緩衝區所屬的管道
struct pipe_buffer *buf要獲取引用的緩衝區
描述
此函式獲取對 buf 的額外引用。它用於 tee() 系統呼叫,當我們複製一個管道中的緩衝區到另一個管道中時。
-
void generic_pipe_buf_release(struct pipe_inode_info *pipe, struct pipe_buffer *buf)¶
釋放對
struct pipe_buffer的引用
引數
struct pipe_inode_info *pipe緩衝區所屬的管道
struct pipe_buffer *buf要釋放引用的緩衝區
描述
此函式釋放對 buf 的引用。