linux系統調用和用戶編程接口(api)html
系統調用是指在操做系統提供給用戶程序調用的一組「特殊」的接口,用戶程序能夠經過這組特殊的接口來獲取操做系統內核提供的服務,例如用戶能夠經過進程控制相關的系統調用來建立進程,實現進程調度,進程管理linux
爲何用戶不能直接訪問系統內核提供的服務?這是由於在linux中,爲了更好地保護內核空間,將程序運行的空間分爲內核空間和用戶空間(也就是常稱爲的內核態和用戶態)程序員
內核態和用戶態運行在不一樣的級別上,在邏輯上也是相互隔離的,新詞用戶進程在一般狀況下是不容許範圍內核數據,也沒法使用內核的函數,他們只能在用戶空間操做用戶數據,調用用戶空間的函數編程
可是,在有些狀況下,用戶空間的進程須要得到必定的系統服務,調用內核空間程序,這時操做系統就必須利用系統提供給用戶的特殊接口,系統調用規定用戶進程進入內核空間的具體位置,進行系統調用的時,程序從用戶空間進入內核空間,處理完後在返回用戶空間windows
linux系統調用部分是很是精簡的系統調用(只有250)他繼承了unix系統調用最基本和最有用的部分,這些系統調用按照功能和邏輯大體能夠分爲api
進程控制,進程間通訊,文件系統控制,系統控制,存儲管理,網絡管理,socket控制,用戶管理緩存
用戶編程的api網絡
前面講到的系統調用便不是直接與程序員進行交互,它僅僅是一個軟中斷機制向內核提出請求,以獲取內核服務的接口,在實際使用中,程序員調用的是用戶編程對應的接口--apisocket
linux中文件及文件描述符概述函數
在linux中對目錄和設備的操做都等同於對文件的操做,所以大大簡化了系統對不一樣設備的處理,linux中的文件主要分爲4種,普通文件,目錄文件,連接文件和設備文件,對於linux而言,全部對設備和文件的操做都是使用文件描述符來進行的
文件描述符是一個非負整數,他是一個索引值,並指向內核中每一個進程打開文件的記錄表,當打開一個現存文件,或者是建立一個新的文件時,內核就像進程返回一個文件描述符,但須要寫入文件時,也須要吧文件描述符做爲參數傳遞給相應的函數
一般一個進程啓動時,都會打開三個文件,標準輸入,標準輸出,標準出錯處理,對應文件描述符爲0,1,2。
基於文件描述符的I/0操做雖然不能移植到類linux之外的系統上去(如windows)但它每每是實現某些I/0操做的惟一途徑,基於文件描述符的I/O操做時linux中對經常使用的操做之一
底層文件I/O操做
這裏主要是5個函數open(),read(),write(),lseek(),和close()這些函數的特色是不帶緩存,直接對文件(包括設備)進行讀寫操做
open()函數用於打開或建立文件,在打開或建立文件時,能夠指定文件的屬性和用戶的權限等各類參數。
close()是一個用於關閉一個被打開的文件。當一個進程終止時,全部被他打開的文件都由內核自動關閉,不少程序都使用這一功能而不顯示的關閉一個文件
read()函數用於將從指定的文件描述符中讀取數據放到緩存區,並返回實際讀入的字節數,若返回0,則表示沒有數據可讀,即已經達到文件尾,讀操做文件從文件的當前指針位置開始,當從終端設備文件中讀取數據時,一般一次最多讀取一行
write()函數用於向打開的文件中寫入數據,寫操做從文件的當前指針位置開始,對磁盤文件進行寫操做,若磁盤已經寫滿,或者超出文件的長度,則write()函數返回失敗
lseek()函數用於在指定的文件描述符中將文件的指針定位到相應的位置,它只能用在可定位(可隨機訪問)文件操做中,管道,套接字,和大部分字符設備文件是不可定位的,因此在這些文件的操做中沒法使用lseek
open函數的原型 int open(const char *pathname ,int flags);pathname是指文件的路徑名和名稱,能夠是絕對路徑或者是相對路徑,flag 是指定了文件的打開方式
O_RDONLY 以只讀方式,要求文件存在
O_WRONLY以只寫的方式打開,要求文件存在
O_RDWR可讀可寫的方式打開,要求文件存在
O_CREAT 建立文件
O_EXCL建立互斥
O_APPEND 以追加的方式寫入首先要有寫權限
O_TRUNC 清空原文件內容
返回值 爲文件描述符,非負整數,文件後續操做的標誌
open的另一種原型爲int open(const char *pathname,int flags,mode_t mode)前面的參數和同樣,mode是指建立文件時的權限0x777 0x644 0x664等等
打開文件失敗的緣由分析:1文件不存在時指定可讀,2文件所在目錄無操做權限 3其餘緣由,文件操做權限,文件是否可用
close函數 函數原型爲int close (int fd);
fd爲open返回值的文件描述符,關閉文件後,該文件描述符將不可再用,返回值表示關閉是否成功,但咱們編程時不處理該返回值,打開文件必須關閉,不然會形成文件描述符的泄漏,特別是異常狀況,能夠關閉0,1,2;
示例代碼:
read 函數原型爲 int read(int fd, void *buf,int count);fd爲文件描述符(注意此處不能是文件名),buf爲存儲讀取的內容的內存地址(指針),必定不能是野指針或者是空指針,count是本次讀取的字節數,要求count要小於等於buf的大小,若是存儲字符串時,返回值爲成功讀取的字節數,若是讀取失敗,返回小於0的值,返回值爲0表示讀取到文件末尾
示例代碼:
#include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> int main(void) { int fd1,size; char buf[128]; fd1 = open("/etc/net/works",O_RDONLY); if(fd1<0) { printf("open fail\n"); exit(0); } while(1) { size = read(fd1,buf,64); if(size<0) { printf("read error\n"); exit(1); } if(size ==0) break; buf[size+1] = '\0'; printf("%s",buf); } close(fd1); return 0; }
memset用於在某段內存中填充那一個數,函數包含的頭文件是#include<string.h>函數原型爲
void *memset(void *s,int c,size_t n);例如memset(buf,0,,128);
注意 :read函數會自動對文件的操做位置進行偏移,讀完幾個字節,以後就偏移幾個字節,自動偏移,若是到達文件末尾,不能再次偏移
若是讀取失敗的緣由:
1文件的讀取權限問題
2,文件沒有內容,須要注意,若是使用O_TRUNC時,文件內容已經被清楚
3:若是該處出現段錯誤,這主要考慮內存指針是否爲野指針或者是否越界
write函數;函數原型爲 int write(int fd, void *buf,int count);
fd爲寫入的文件描述符,buf爲須要寫入的內容的指針,count是寫入的字節數,這裏的buf要小於buf的有效值,返回值爲成功寫入的字節數,返回值小於0表示寫入失敗
write也會對文件的操做位置進行偏移,若是爲追加方式時,從文件的末尾開始寫入,若是寫入失敗,若是寫入失敗,這分析緣由爲:1)文件是否有寫權限,2)文件寫入多錯誤時,能夠查看內存是否越界,3)注意使用)O_TRUNC會清空原內容
#include<stdio.h> #include<sys/stat.h> #include<sys/types.h> #include<fcntl.h> #include<string.h> #include<unistd.h> int main(void) { int fd1,fd2,size,f3; char buf[128]; fd1 = open("/etc/xinetd.d/daytime",O_RDONLY); if(fd1<0) { printf("open fail\n"); exit(1); } fd2 = open(""daytime1",O_RDWR|O_CREAT,777); if(fd2<0) { 1,1 Top printf("create daytime1 fail\n"); exit(1); } while(1) { memset(buf,0,127); size = read(fd1,buf,127); if(size<0) { printf("read fail\n"); exit(1); } if(size==0) break; buf[128]='\0'; printf("%s",buf); f3 = write(fd2,buf,size); if(f3<0) { printf("write fail\n"); exit(1); } } close(fd1); close(fd2); return 0; }
版權全部,轉載請註明轉載地址:http://www.cnblogs.com/fengdashen/p/3300614.html