linux 0 11 核心學習 pipe c

2021-08-25 01:22:47 字數 4710 閱讀 6367

* 該檔案中的兩個函式read_pipe和write_pipe是上層函式

* read和write的底層實現

* linux/fs/pipe.c

* (c) 1991 linus torvalds

#include

#include

// 記憶體管理標頭檔案。含有頁面大小定義和一些頁面釋放函式原型

#include /* for get_free_page */

#include

/* pipe類似於佇列,向pipe的尾部寫入資料,從pipe的頭部讀取資料 */

/* 管道讀操作函式 */

/* 引數inode 是管道對應的i 節點,buf 是資料緩衝區指標,count 是讀取的位元組數 */

* read_pipe()函式用於讀取管道中的資料,如果管道中沒有資料的話,

* 喚醒寫管道程序,自己睡眠,如果讀到資料,並把資料傳到使用者緩衝區,

* 當把管道中所有的資料都取走後,也要喚醒等待寫管道的程序,並返回

* 已讀資料位元組數

int read_pipe(struct m_inode * inode, char * buf, int count)

int chars, size, read = 0;

while (count>0)

// 若當前管道中沒有資料(size=0),則喚醒等待該節點的程序

while (!(size=pipe_size(*inode)))

wake_up(&inode->i_wait);

// 如果已沒有寫管道者

if (inode->i_count != 2) /* are there any writers? */

return read; // 返回已讀位元組數

// 否則在該i 節點上睡眠,等待資訊

sleep_on(&inode->i_wait);

// 取管道尾到緩衝區末端的位元組數chars

chars = page_size-pipe_tail(*inode);

if (chars > count)

chars = count;

if (chars > size)

chars = size;

// 讀位元組計數減去此次可讀的位元組數chars,並累加已讀位元組數

count -= chars;

read += chars;

// 令size 指向管道尾部,調整當前管道尾指標(前移chars 位元組)

size = pipe_tail(*inode);

pipe_tail(*inode) += chars;

pipe_tail(*inode) &= (page_size-1);

// 將管道中的資料複製到使用者緩衝區中

while (chars-->0)

put_fs_byte(((char *)inode->i_size)[size++],buf++);

// 喚醒等待該管道i 節點的程序

wake_up(&inode->i_wait);

// 返回讀取的位元組數

return read;

* 函式read_pipe首先檢查管道中是否含有資料,沒有的話

* 喚醒等待程序。然後得到管道的尾指標,將尾指標位置向

* 前移動size個位元組,最後將資料複製到使用者程式區

* tail | | head

* write the data get the data

/* 想管道中寫入資料,引數inode是管道對應的i節點,buf是資料緩衝區 */

/* count是寫入管道的位元組數 */

int write_pipe(struct m_inode * inode, char * buf, int count)

int chars, size, written = 0;

while (count>0)

// 若當前管道中沒有已經滿了(size=0),則喚醒等待該節點的程序

while (!(size=(page_size-1)-pipe_size(*inode)))

wake_up(&inode->i_wait);

// 如果已沒有讀管道者

if (inode->i_count != 2) { /* no readers */

// 向程序傳送sigpipe訊號

current->signal |= (1<<(sigpipe-1));

// 並返回已寫入的位元組數並退出

return written?written:-1;

// 睡眠,等待管道騰出空間

sleep_on(&inode->i_wait);

// 取管道頭部到緩衝區末端空間位元組數chars。如果其大於還需要寫入的位元組數count,則令其等於

// count。如果chars 大於當前管道中空閒空間長度size,則令其等於size

chars = page_size-pipe_head(*inode);

if (chars > count)

chars = count;

if (chars > size)

chars = size;

// 寫入位元組計數減去此次可寫入的位元組數chars,並累加已寫位元組數到written

count -= chars;

written += chars;

// 令size 指向管道資料頭部,調整當前管道資料頭部指標

size = pipe_head(*inode);

pipe_head(*inode) += chars;

pipe_head(*inode) &= (page_size-1);

// 從使用者緩衝區複製chars 個位元組到管道中

while (chars-->0)

((char *)inode->i_size)[size++]=get_fs_byte(buf++);

// 喚醒等待該i 節點的程序,返回已寫入的位元組數,退出

wake_up(&inode->i_wait);

return written;

* 該函式首先是得到管道的長度,如果管道已滿的話,喚醒等待的程序

* 否則得到管道頭,移動管道頭指標,將資料從使用者區寫到管道中

/* 建立管道系統呼叫函式,fileds[2],fileds[0]用於讀管道中資料,fileds[1] */

/* 用於向管道中寫入資料,成功時返回0,出錯時返回-1 */

int sys_pipe(unsigned long * fildes)

struct m_inode * inode;

struct file * f[2];

int fd[2];

int i,j;

// 從系統檔案表中取兩個空閒項(引用計數字段為0 的項),並分別設定引用計數為1

j=0;

for(i=0;j<2 && iif (!file_table[i].f_count)

(f[j++]=i+file_table)->f_count++;

// 如果只有乙個空閒項,則釋放該項(引用計數復位)

if (j==1)

f[0]->f_count=0;

// 如果沒有找到兩個空閒項,則返回-1

if (j<2)

return -1;

// 針對上面取得的兩個檔案結構項,分別分配一檔案控制代碼,並使程序的檔案結構指標分別指向這兩個

// 檔案結構

j=0;

for(i=0;j<2 && iif (!current->filp[i])

current->filp[ fd[j]=i ] = f[j];

j++;

// 如果只有乙個空閒檔案控制代碼,則釋放該控制代碼

if (j==1)

current->filp[fd[0]]=null;

// 如果沒有找到兩個空閒控制代碼,則釋放上面獲取的兩個檔案結構項(復位引用計數值)

if (j<2) {

f[0]->f_count=f[1]->f_count=0;

return -1;

// 申請管道i 節點,並為管道分配緩衝區(1 頁記憶體)

if (!(inode=get_pipe_inode())) // 不成功 ?

// 相應釋放兩個檔案控制代碼和檔案結構項

current->filp[fd[0]] =

current->filp[fd[1]] = null;

f[0]->f_count = f[1]->f_count = 0;

return -1; // 返回值

// 初始化兩個檔案指標,將f[2]複製到fileds[2]中,將核心資料複製

// 到使用者資料中

f[0]->f_inode = f[1]->f_inode = inode;

f[0]->f_pos = f[1]->f_pos = 0;

f[0]->f_mode = 1; /* read */

f[1]->f_mode = 2; /* write */

put_fs_long(fd[0],0+fildes);

put_fs_long(fd[1],1+fildes);

// 返回成功0

return 0;

* 該函式實現的是系統呼叫。首先是查詢全域性的file_table來找到

* 兩個空閒項,如果成功的話,設定當前程序的檔案結構表項。申請

* i節點,將資料複製到結果中去

參考《linux核心完全注釋》和網上資料

Linux 0 11 核心筆記

1 任務0的堆疊問題 一直不明白schedule.c裡的task union的stack和user stack是什麼關係,head.s裡就設定了esp指向user stack,卻一直沒有用到task union,直到看到init task才明白,從進入保護模式到跳轉進使用者態都是用的user sta...

Linux0 11核心筆記( )

c語言 彙編知識 嵌入式彙編 x86處理器和程式設計的相關知識和 unix作業系統設計 linus在最初開發linux作業系統時參考了minix作業系統 作業系統 設計與實現 一種基於訊息傳遞在核心各模組之間進行通訊 資訊交換 重要的五個支柱 unix作業系統 分時作業系統 minix作業系統 gn...

Linux 0 11核心編譯問題

弄了好長時間,只是可以用linux 0.11我的linux實驗室環境,使用bochs模擬,進入linux 0.11 cd cd src linux make 這樣就編譯成image了 mkdir a mkdir a boot mcopy image a boot 將映象檔案拷貝到啟動軟盤 修改men...