最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

一文講解linux-文件系統(tǒng)調(diào)用-基于C語(yǔ)言

2022-08-23 17:48 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

是操作系統(tǒng)提供的、與用戶程序之間的接口,也就是操作系統(tǒng)提供給程序員的接口。從感覺(jué)上系統(tǒng)調(diào)用類似于過(guò)程調(diào)用,都由程序代碼構(gòu)成,使用方式相同,但兩者有實(shí)質(zhì)差別:過(guò)程調(diào)用只能在用戶態(tài)下運(yùn)行,不能進(jìn)入核心態(tài);而系統(tǒng)調(diào)用可以實(shí)現(xiàn)從用戶態(tài)到核心態(tài)的轉(zhuǎn)變。



Linux文件描述符

文件描述符fd是進(jìn)程打開(kāi)文件列表中的序號(hào),它是一個(gè)0~255的整數(shù)。文件描述符0、1、2分別用于表示標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤文件。進(jìn)程打開(kāi)一個(gè)文件后,就一直使用文件描述符fd來(lái)對(duì)文件進(jìn)行標(biāo)識(shí)并進(jìn)行各種操作,它是文件正在被進(jìn)程使用的標(biāo)志。




open系統(tǒng)調(diào)用

調(diào)用open可以打開(kāi)或創(chuàng)建一個(gè)文件。


#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

int open(const char *pathname, int oflag, ... /* mode_t mode */);

返回:若成功為文件描述符,若出錯(cuò)為- 1

我們將第三個(gè)參數(shù)寫(xiě)為. . .,這是ANSI C說(shuō)明余下參數(shù)的數(shù)目和類型可以變化的方法。對(duì)于open函數(shù)而言,僅當(dāng)創(chuàng)建新文件時(shí)才使用第三個(gè)參數(shù)。在函數(shù)原型中此參數(shù)放置在注釋中。

第一個(gè)參數(shù)**pathname*是要打開(kāi)或創(chuàng)建的文件的名字。

第二個(gè)參數(shù)oflag參數(shù)可用來(lái)說(shuō)明此函數(shù)的多個(gè)選擇項(xiàng)。用下列一個(gè)或多個(gè)常數(shù)進(jìn)行或運(yùn)算構(gòu)成oflag*參數(shù)(這些常數(shù)定義在< fcntl . h >頭文件中, 在這三個(gè)常數(shù)中應(yīng)當(dāng)只指定一個(gè)):

  • O_RDONLY 只讀打開(kāi)

  • O_WRONLY 只寫(xiě)打開(kāi)

  • O_RDWR 讀、寫(xiě)打開(kāi)

第三個(gè)可選參數(shù):

  • O_APPEND 每次寫(xiě)時(shí)都加到文件的尾端。

  • O_CREAT 若此文件不存在則創(chuàng)建它。使用此選擇項(xiàng)時(shí),需同時(shí)說(shuō)明第三個(gè)參數(shù)mode,用其說(shuō)明該新文件的存取許可權(quán)位。

  • O_EXCL 如果同時(shí)指定了O_CREAT,而文件已經(jīng)存在,則出錯(cuò)。這可測(cè)試一個(gè)文件是否存在。

  • O_TRUNC 如果此文件存在,而且為只讀或只寫(xiě)成功打開(kāi),則將其長(zhǎng)度截短為0。

  • O_NONBLOCK 如果pathname指的是一個(gè)FIFO、一個(gè)塊特殊文件或一個(gè)字符特殊文件,則此選擇項(xiàng)為此文件的本次打開(kāi)操作和后續(xù)的I / O操作設(shè)置非阻塞方式。

  • O_SYNC 使每次write都等到物理I / O操作完成。

由open函數(shù)返回的文件描述符一定是最小的未用描述符數(shù)字。

舉例:

int fd; ? ? ? ? ? ? ? ? ? ?//定義一個(gè)整型的文件描述符
char path[]=“/proc/version” ? ? //記錄Linux內(nèi)核版本的文件
fd=open(path,O_RDONLY) ? //以只讀方式打開(kāi)

close調(diào)用

可用close關(guān)閉一個(gè)打開(kāi)文件:

#include <unistd.h>

int close (int fd);

返回:若成功為0,若出錯(cuò)為-1

關(guān)閉一個(gè)文件時(shí)也釋放該進(jìn)程加在該文件上的所有記錄鎖。當(dāng)一個(gè)進(jìn)程終止時(shí),它所有的打開(kāi)文件都由內(nèi)核自動(dòng)關(guān)閉。


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺(jué)得比較好的學(xué)習(xí)書(shū)籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書(shū)、實(shí)戰(zhàn)項(xiàng)目及代碼)? ??

lseek調(diào)用

每個(gè)打開(kāi)的文件都有一個(gè)與其相關(guān)聯(lián)的“當(dāng)前文件位移量”。它是一個(gè)非負(fù)整數(shù),用以度量從文件開(kāi)始處計(jì)算的字節(jié)數(shù)。通常,讀、寫(xiě)操作都從當(dāng)前文件位移量處開(kāi)始,并使位移量增加所讀或?qū)懙淖止?jié)數(shù)。按系統(tǒng)默認(rèn),當(dāng)打開(kāi)一個(gè)文件時(shí),除非指定O_APPEND選擇項(xiàng),否則該位移量被設(shè)置為0。

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence) ;

返回:若成功為新的文件位移,若出錯(cuò)為-1

對(duì)參數(shù)offset 的解釋與參數(shù)whence的值有關(guān)

  • 若whence是SEEK_SET,則將該文件的位移量設(shè)置為距文件開(kāi)始處offset 個(gè)字節(jié)

  • 若whence是SEEK_CUR,則將該文件的位移量設(shè)置為其當(dāng)前值加offset, offset可為正或負(fù)

  • 若whence是SEEK_END,則將該文件的位移量設(shè)置為文件長(zhǎng)度加offset, offset可為正或負(fù)

若lseek成功執(zhí)行,則返回新的文件位移量,為此可以用下列方式確定一個(gè)打開(kāi)文件的當(dāng)前位移量:

off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);

這種方法也可用來(lái)確定所涉及的文件是否可以設(shè)置位移量。如果文件描述符引用的是一個(gè)管道或FIFO,則lseek返回-1,并將errno設(shè)置為EPIPE。

lseek僅將當(dāng)前的文件位移量記錄在內(nèi)核內(nèi),它并不引起任何I / O操作。然后,該位移量用于下一個(gè)讀或?qū)懖僮鳌?/p>

文件位移量可以大于文件的當(dāng)前長(zhǎng)度,這種情況下,對(duì)該文件的下一次寫(xiě)將延長(zhǎng)該文件并在文件中構(gòu)成一個(gè)空洞,這一點(diǎn)是允許的。位于文件中但沒(méi)有寫(xiě)過(guò)的字節(jié)都被讀為0。

read調(diào)用

用read從打開(kāi)的文件中讀數(shù)據(jù)。

#include <unistd.h>
ssize_t read(int fd, void *buff, size_t nbytes) ;

返回:讀到的字節(jié)數(shù),若已到文件尾為0,若出錯(cuò)為-1

write調(diào)用

用write函數(shù)向打開(kāi)文件寫(xiě)數(shù)據(jù)。

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t nbytes) ;

返回:若成功為已寫(xiě)的字節(jié)數(shù),若出錯(cuò)為-1

其返回值通常與參數(shù)nbytes的值不同,否則表示出錯(cuò)。write出錯(cuò)的一個(gè)常見(jiàn)原因是:磁盤已寫(xiě)滿,或者超過(guò)了對(duì)一個(gè)給定進(jìn)程的文件長(zhǎng)度限制。

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

unlink調(diào)用

unlink()函數(shù)功能即為刪除文件。執(zhí)行unlink()函數(shù)會(huì)刪除所給參數(shù)指定的文件。

#include<unistd.h>
int unlink(const char *pathname); // pathname:指定要移除的鏈接文件。

成功返回0;失敗則返回-1,同時(shí)設(shè)置errno為相應(yīng)值。

執(zhí)行unlink()函數(shù)并不一定會(huì)真正的刪除文件,它先會(huì)檢查文件系統(tǒng)中此文件的連接數(shù)是否為1,如果不是1說(shuō)明此文件還有其他鏈接對(duì)象,因此只對(duì)此文件的連接數(shù)進(jìn)行減1操作。若連接數(shù)為1,并且在此時(shí)沒(méi)有任何進(jìn)程打開(kāi)該文件,此內(nèi)容才會(huì)真正地被刪除掉。在有進(jìn)程打開(kāi)此文件的情況下,則暫時(shí)不會(huì)刪除,直到所有打開(kāi)該文件的進(jìn)程都結(jié)束時(shí)文件就會(huì)被刪除。

文件鎖

fcntl函數(shù)可以改變已經(jīng)打開(kāi)文件的性質(zhì)。

#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd,.../* int arg * / );

返回:若成功則依賴于cmd(見(jiàn)下),若出錯(cuò)為-1

  • fcntl函數(shù)有5種功能:

  • 復(fù)制一個(gè)現(xiàn)有的描述符(cmd=F_DUPFD).

  • 獲得/設(shè)置文件描述符標(biāo)記(cmd=F_GETFD或F_SETFD).

  • 獲得/設(shè)置文件狀態(tài)標(biāo)記(cmd=F_GETFL或F_SETFL).

  • 獲得/設(shè)置異步I/O所有權(quán)(cmd=F_GETOWN或F_SETOWN).

  • 獲得/設(shè)置記錄鎖(cmd=F_GETLK,F_SETLK或F_SETLKW).

當(dāng)多個(gè)用戶共同使用、操作一個(gè)文件也即文件共享的情況下,Linux通常采用給文件上鎖的方法來(lái)避免產(chǎn)生競(jìng)爭(zhēng)。

文件鎖的數(shù)據(jù)結(jié)構(gòu):

struct flock{
 ? short l_type; ?// ?鎖類型,可取值為F_RDLCK、F_WRLCK、F_UNLCK
 ? off_t l_start; ?// 相對(duì)偏移量
 ? short l_whence; // 位移量起點(diǎn):SEEK_SET文件開(kāi)頭、SEEK_CUR文件指針當(dāng)前位置、SEEK_END文件尾 ?
 ? off_t l_len; ? // ?加鎖區(qū)域長(zhǎng)度
 ? pid_t l_pid; ? // ?加鎖進(jìn)程的進(jìn)程號(hào)
}

拓展

/proc 文件系統(tǒng)是一種內(nèi)核和內(nèi)核模塊用來(lái)向進(jìn)程 (process) 發(fā)送信息的機(jī)制。這個(gè)偽文件系統(tǒng)讓你可以和內(nèi)核內(nèi)部數(shù)據(jù)結(jié)構(gòu)進(jìn)行交互,獲取有關(guān)進(jìn)程的有用信息,在運(yùn)行中改變?cè)O(shè)置。與其他文件系統(tǒng)不同,/proc 存在于內(nèi)存之中而不是硬盤上。proc 文件系統(tǒng)可以被用于收集有用的關(guān)于系統(tǒng)和運(yùn)行中的內(nèi)核的信息。

下面是一些重要的文件:

  • /proc/cpuinfo - CPU 的信息 (型號(hào), 家族, 緩存大小等)

  • /proc/meminfo - 物理內(nèi)存、交換空間等的信息

  • /proc/mounts - 已加載的文件系統(tǒng)的列表

  • /proc/devices - 可用設(shè)備的列表

  • /proc/filesystems - 被支持的文件系統(tǒng)

  • /proc/modules - 已加載的模塊

  • /proc/version - 內(nèi)核版本

  • /proc/cmdline - 系統(tǒng)啟動(dòng)時(shí)輸入的內(nèi)核命令行參數(shù)

有一些以數(shù)字命名的目錄,它們是進(jìn)程目錄。系統(tǒng)中當(dāng)前運(yùn)行的每一個(gè)進(jìn)程在/proc下都對(duì)應(yīng)一個(gè)以進(jìn)程號(hào)為目錄名的目錄/proc/pid,它們是讀取進(jìn)程信息的接口。

通過(guò) /proc 中可讀寫(xiě)的文件提供了對(duì)內(nèi)核的交互機(jī)制。寫(xiě)這些文件可以改變內(nèi)核的狀態(tài)。大部分 /proc 的文件是只讀的,/proc/sys 目錄存放所有可讀寫(xiě)的文件的目錄,可以被用于改變內(nèi)核行為, /proc/sys/kernel目錄包含反通用內(nèi)核行為的信息。

實(shí)驗(yàn)

編寫(xiě)兩個(gè)源代碼文件read_lock.c和write_lock.c,分別調(diào)用lock_set函數(shù)對(duì)文件加讀鎖和寫(xiě)鎖。

// lock.c 實(shí)現(xiàn)加鎖
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int lock_set(int fd,int type)
{
	struct flock old_lock,lock;

	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	lock.l_type = type;
	lock.l_pid = -1;

	fcntl(fd,F_GETLK,&lock);
	if(lock.l_type != F_UNLCK)
	{
		if(lock.l_type == F_RDLCK)
			printf("Read lock already set by %d\n",lock.l_pid);
		else if(lock.l_type == F_WRLCK)
			printf("Write lock already set by %d\n",lock.l_pid);
	}

	lock.l_type = type;

	if((fcntl(fd,F_SETLKW,&lock)) < 0)
	{
		printf("Lock failed:type = %d\n",lock.l_type);
		return 1;
	}

	switch(lock.l_type)
	{
		case F_RDLCK:
			printf("Read lock set by %d\n",getpid());
			break;
		case F_WRLCK:
			printf("Write lock set by %d\n",getpid());
			break;
		case F_UNLCK:
			printf("Release lock set by %d\n",getpid());
			return 1;
			break;
		default:
			break;
	}
	return 0;
}
// 讀鎖
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#include <stdio.h>
#include "lock.c"

int main(){
	char filepath[] = "./test";
	int fd = open(filepath, O_RDONLY);
	lock_set(fd, F_RDLCK);

	getchar();
	return 0;
}
// 寫(xiě)鎖
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#include <stdio.h>
#include "lock.c"

int main(){
	char filepath[] = "./test";
	int fd = open(filepath, O_WRONLY);
	lock_set(fd, F_WRLCK);
	
	getchar();
	return 0;
}


一文講解linux-文件系統(tǒng)調(diào)用-基于C語(yǔ)言的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
平凉市| 河池市| 玛纳斯县| 济阳县| 浠水县| 九江市| 怀安县| 仙桃市| 贵溪市| 玉门市| 繁昌县| 安丘市| 盘山县| 蓬莱市| 公主岭市| 怀安县| 进贤县| 锡林郭勒盟| 吉林市| 呼玛县| 长武县| 泌阳县| 藁城市| 客服| 环江| 天门市| 平武县| 珲春市| 乌兰察布市| 鞍山市| 都安| 府谷县| 鄄城县| 岫岩| 崇义县| 宿迁市| 隆化县| 镇坪县| 女性| 株洲县| 贵定县|