欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Linux操作文件的底層系統(tǒng)調(diào)用,探究父子進程是否可以共享文件問題

 更新時間:2023年03月23日 15:28:10   作者:Dutkig  
這篇文章主要介紹了Linux操作文件的底層系統(tǒng)調(diào)用,探究父子進程是否可以共享文件問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

linux操作系統(tǒng)奉行一切皆文件的理念,所有文件設(shè)備幾乎都可以用一套系統(tǒng)調(diào)用即open()/close()/write()/read()等來操作。系統(tǒng)調(diào)用和C庫調(diào)用操作文件類似。Linux自帶的man手冊是最權(quán)威的。通過查看man手冊來查看系統(tǒng)調(diào)用用法。

代號 —— 代表的含義

  • 1 —— 用戶在shell環(huán)境下可操作/可執(zhí)行的命令
  • 2 —— 系統(tǒng)內(nèi)核可調(diào)用的函數(shù)與工具
  • 3 —— 一些常用的函數(shù)與函數(shù)庫,大部分C的函數(shù)庫
  • 4 —— 設(shè)備文件的說明,通常是在 /dev下的設(shè)備
  • 5 —— 配置文件或某些文件的格式
  • 6 —— 游戲
  • 7 —— 管理與協(xié)議等,例如Linux文件系統(tǒng)、網(wǎng)絡(luò)協(xié)議等
  • 8 —— 系統(tǒng)管理員可用的命令
  • 9 —— 與Kernel有關(guān)的文件

注意,系統(tǒng)的頭文件在Linux中一般存放在/usr/include目錄下;下面包含的一些頭文件有的帶了sys,其實是include底下的子目錄中的頭文件

open()——打開或者創(chuàng)建一個文件

返回值類型: int——文件描述符fd,每打開一個文件,就會得到一個文件描述符,這個文件描述符是整形的,我們通過文件描述符進行讀寫操作。

  • 失?。?1
  • 成功:>= 0,即文件描述符;
  • mode_t是一個類型別名,實際上就是一個有符號的整數(shù),對open函數(shù)而言,僅僅當創(chuàng)建新文件時才使用第三個參數(shù)

flag:打開標志

注意: 這些其實都是定義的一些宏,當需要使用到多個參數(shù)時,使用按位或“ | ”構(gòu)成多個flag參數(shù)

也可跟隨下面的方式一起使用:

其他不一一介紹,需要使用時自查。

write()

返回值

  • 若成功為已經(jīng)寫入的字節(jié)數(shù);
  • 若出錯為-1;

注意:計劃寫入的字節(jié)數(shù)和函數(shù)的返回值不相等時,表示寫入出現(xiàn)了錯誤,可以用來檢驗寫入是否成功;

參數(shù):

  • fd:寫入文件的文件描述符;
  • buf:存放待寫數(shù)據(jù)的緩存;
  • count:要求寫入一次數(shù)據(jù)的字節(jié)數(shù);

注意:

對于普通文件,寫操作從文件的當前位移量處開始,若如果在打開該文件時,指定了O_APPEND選擇項,則在每次寫操作之前,將文件位移量設(shè)置在文件的當前結(jié)尾處。在一次成功寫之后,該文件位移量增加實際寫的字節(jié)數(shù)。

read()

返回值 :讀到的字節(jié)數(shù)

  • 若已到文件尾為0;若出錯為-1;

參數(shù)

  • fd:讀取文件的文件描述符;
  • buf:存放讀取數(shù)據(jù)的緩存;
  • count:要求讀取一次數(shù)據(jù)的字節(jié)數(shù);注意返回值是實際讀到的字節(jié)數(shù),二者并不相同;

注意:讀操作從文件的當前位移量開始,在成功返回之前,該位移量增加實際讀得的字節(jié)數(shù)(這個位移量是可以自己設(shè)置的);

close()

注意:當一個進程終止時,它所打開的文件都由內(nèi)核自動關(guān)閉。

注:這些不帶緩存的函數(shù)都是內(nèi)核提供的系統(tǒng)調(diào)用;這正是和我們在C語言中學到的那些IO操作不同的地方,他們不是標準C的組成部分,但是POSIX的組成部分。

標準C對文件操作時都是通過對FILE的結(jié)構(gòu)體指針進行操作的,而這里使用的是文件描述符。

文件描述符的范圍是0——OPEN MAX,早期的Unix采用的上限為19(即允許每個進程打開20個文件),現(xiàn)在很多系統(tǒng)將即增加到63,Linux為1024,具體多少可以在<unistd.h>的頭文件中查找。

文件描述符與文件指針

  • FILE *fdopen(int fd,const char *mode),將文件描述符轉(zhuǎn)為文件指針;
  • int fileno(FILE *stream),將文件指針轉(zhuǎn)換為文件描述符;

lseek函數(shù)

功能: 定位一個已打開的文件

off_t lseek(int fd,off_t offset,int whence);
  • fd:已經(jīng)打開的文件描述符;
  • offset:位移量;
  • whence:定位的位置,即基準點
  • SEEK_SET:將該文件的位移量設(shè)置為距文件開始處offset個字節(jié);
  • SEEK_CUR:將該文件的位移量設(shè)置為其當前值加offset,offset可正可負;
  • SEEK_END:將該文件的位移量設(shè)置為文件長度加offset,offset可正可負(此時若為正值,就涉及到空洞文件了,請看下面的講解);
  • 返回值:**若成功則返回新的文件位移量(絕對位移量)**若出錯為-1;定位到文件尾部時,可以返回文件的大??;
  • lseek函數(shù)也可以用來確定所涉及的文件是否可以設(shè)置位移量,如果文件描述符所引用的是一個管道或者FIFO,則lseek返回-1,并將errno設(shè)置為EPLPE;

空洞文件示例:

#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>

//生成空洞文件
char *buffer = "0123456789";

int main(int argc,char *argv[])
{
	if(argc < 2)
	{
		fprintf(stderr,"-usage:%s [file]\n",argv[0]);
		exit(1);
	}

	int fd = open(argv[1],O_WRONLY | O_CREATE | O_TRUNC,0777);
	if(fd < 0)
	{
		perror("open error");
		exit(1);
	}

	size_t size = strlen(buffer) * sizeof(char);
	//將字符串寫入到空洞文件中
	if(write(fd,buffer,size) != size)
	{
		perror("write error");
		exit(1);
	}
	
	//定位到文件尾部的10個字節(jié)處
	if(lseek(fd,10L;SEERK_END) < 0)
	{
		perror("lseek error");
		exit(1);
	}
	//從文件尾部的10個字節(jié)處再寫入字符串
	if(write(fd,buffer,size) != size)
	{
		perror("write error");
		exit(1);
	}
	close(fd);
	return 0;
}

我們可以看到用more命令查看文件內(nèi)容時,發(fā)現(xiàn)顯示的內(nèi)容只有一次寫入的結(jié)果,用od

-c命令查看文件的ASSCI碼,我們會發(fā)現(xiàn)在兩次內(nèi)容之間,有10個\0,這就是空洞,用vim打開該文件內(nèi)容也可以看到,有10個^@符。

注:每個文件都有一個與其相關(guān)聯(lián)的“當前文件偏移量”,它是一個非負整數(shù),用以度量從文件開始處計算的字節(jié)數(shù)。通常讀寫操作都以文件當前偏移量處開始,并使得偏移量增加所讀或所寫的字節(jié)數(shù)。按系統(tǒng)默認,當打開一個文件時,除非指定O_APPEND選擇項,否則該文件位移量被設(shè)置為0;

示例:

運行結(jié)果如下:

fd = 3的原因是:

系統(tǒng)內(nèi)部PCB存在一個文件表,以記錄打開的文件,文件描述符其實就是文件表的下標

  • 0——FILE* stdin,標準輸入
  • 1——FILE* stdout,標準輸出
  • 3——FILE* stderr,標準錯誤輸出
  • 本程序已經(jīng)默認打開了三個文件,fd排到第四個,所以編號為3

接下來進行文件讀取

運行結(jié)果如下:

應(yīng)用:利用讀寫對文件進行復制

首先聲明:我們不區(qū)分文本文件還是二進制文件

完成對一個圖片的復制,我們可以使用以下的方案:

  • 先打開原來的二進制文件
  • 打開一個新的文件
  • 從原來的二進制文件中讀取一部分寫入新文件
  • 反復讀寫
  • 直到讀完,寫完就停止【read() == 0作為循環(huán)停止的條件,讀不到就是讀完了】
  • 完成復制

復制完成

打開文件后,fork的子進程能否共享和父進程共享訪問同一個文件?

我們每次打開文件以后,會在內(nèi)核中產(chǎn)生struct file這樣一個結(jié)構(gòu)體,以表示打開的文件,記錄著以下信息:

  • 文件偏移量(起始從0開始,文件指針隨著寫入數(shù)據(jù)進行偏移)
  • 引用計數(shù)(幾個進程正在使用這個打開的文件)
  • inode節(jié)點(存放進程的屬性信息:誰創(chuàng)建了,名字是什么,在磁盤哪里存儲。通過這個inode節(jié)點,我們才能找到對應(yīng)的這個具體的文件)
  • 打開方式:比如只讀方式,只寫方式打開

測試1:先打開文件再fork

close(fd)寫在最外側(cè),父子進程都會關(guān)閉,每關(guān)閉一次,引用計數(shù)減1,直到為0。

運行結(jié)果如下:

原因如下:

測試2:先fork再打開文件

修改代碼后,運行結(jié)果發(fā)生如下變化:

因為父子進程分離后,打開了各自的文件,產(chǎn)生了各自的struct file,不再共享文件偏移量。

在實際的應(yīng)用場景中,我們更多地使用父進程打開的文件,子進程去訪問這種形式。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • linux編程之pipe()函數(shù)詳解

    linux編程之pipe()函數(shù)詳解

    本篇文章主要介紹了linux編程之pipe()函數(shù)詳解,具有一定的參考價值,有需要的可以了解一下。
    2016-11-11
  • Mac OS X中設(shè)置VIM語法高亮的方法

    Mac OS X中設(shè)置VIM語法高亮的方法

    大家應(yīng)該都知道在默認情況下,使用vim打開文本文件都是灰蒙蒙的一片,當我們要在其中查詢某個字符的時候也看的不清楚。但是,其實是有辦法解決這種困境。下面這篇文章就給給大家分享了在Mac OS X中設(shè)置VIM語法高亮的方法,有需要的朋友們可以參考借鑒,下面來一起看看。
    2016-11-11
  • Linux 下sftp配置之密鑰方式登錄詳解

    Linux 下sftp配置之密鑰方式登錄詳解

    這篇文章主要介紹了Linux 下sftp配置之密鑰方式登錄詳解的相關(guān)資料,為了安全性,需使用sftp,鎖定目錄且不允許sftp用戶登到服務(wù)器,需要的朋友可以參考下
    2016-12-12
  • 記一次linux服務(wù)器入侵應(yīng)急響應(yīng)(小結(jié))

    記一次linux服務(wù)器入侵應(yīng)急響應(yīng)(小結(jié))

    這篇文章主要介紹了記一次linux服務(wù)器入侵應(yīng)急響應(yīng),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-08-08
  • Linux之UDP協(xié)議及其編程全流程

    Linux之UDP協(xié)議及其編程全流程

    這篇文章主要介紹了Linux之UDP協(xié)議及其編程全流程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Linux中使用nfs共享存儲的方式

    Linux中使用nfs共享存儲的方式

    NFS是一種基于TCP/IP傳輸?shù)木W(wǎng)絡(luò)文件系統(tǒng)協(xié)議,通過使用NFS協(xié)議,客戶機可以像訪問本地目錄一樣訪問遠程服務(wù)器中的共享資源,本文給大家介紹Linux中使用nfs共享存儲的相關(guān)知識,感興趣的朋友跟隨小編一起看看吧
    2023-10-10
  • centos7.2.1511安裝jdk1.8.0_151及mysql5.6.38的方法

    centos7.2.1511安裝jdk1.8.0_151及mysql5.6.38的方法

    這篇文章主要介紹了centos7.2.1511安裝jdk1.8.0_151及mysql5.6.38的方法,較為詳細的講述了centos7.2.1511安裝jdk1.8.0_151及mysql5.6.38的具體步驟與相關(guān)設(shè)置技巧,需要的朋友可以參考下
    2018-01-01
  • Linux系統(tǒng)下移植busybox中mkfs.vfat命令

    Linux系統(tǒng)下移植busybox中mkfs.vfat命令

    為了延長磁盤壽命來存儲音視頻文件,打發(fā)在格式化磁盤過程中將簇的大小設(shè)置大點。這接下來通過本文給大家介紹移植busybox中mkfs.vfat命令,需要的朋友可以參考下
    2019-07-07
  • ubuntu中編寫shell腳本開機自動啟動(推薦)

    ubuntu中編寫shell腳本開機自動啟動(推薦)

    這篇文章主要介紹了ubuntu中編寫shell腳本開機自動啟動,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-12-12
  • Linux下用netstat查看網(wǎng)絡(luò)狀態(tài)、端口狀態(tài)

    Linux下用netstat查看網(wǎng)絡(luò)狀態(tài)、端口狀態(tài)

    這篇文章主要介紹了Linux下用netstat查看網(wǎng)絡(luò)狀態(tài)、端口狀態(tài)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-12-12

最新評論