Linux 編程學習筆記(一):文件I/O-open,openat,creat與close

Linux 編程學習筆記(一):文件I/O-open,openat,creat與close

Linux 下文件I/O函數包括以下幾個函數:

  • open 和 openat
  • creat
  • close
  • lseek
  • read
  • write
  • dup,dup2
  • sync,fsync,fdatasync
  • fcntl,ioctl

其中,open openat creat 用於打開/創建文件

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
int openat(int dirfd, const char *pathname, int flags);
int openat(int dirfd, const char *pathname, int flags, mode_t mode);

以上函數成功時返回文件描述符;失敗時返回-1,並設置errno變量。

open openat函數用於打開文件,其中open打開是的相對於程序執行位置路徑的文件,openat打開的是相對於給定文件路徑下的的文件。

flags可以是下列常量或者是由下列常量運算(“|”)組合得到:

O_RDONLY          ;只讀打開
O_WRONLY          ;只寫打開
O_RDWR            ;讀寫打開
O_EXEC            ;只執行打開

上面5個常量只能去一個組成flags。

O_APPEND          ;追加模式,即每次寫入都寫入到文件尾
O_CREAT           ;若文件不存在就自動創建。當使用該選項時,必須指定第三個參數mode(用以指定創建的文件的權限).
O_DIRECTORY       ;若pathname不是目錄,則出錯。
O_EXCL            ;若同時指定了O_CREAT,而文件已經存在,則報錯。用這個可以測試一個文件是否存在,若不存在則創建文件。
O_NOCTTY          ;若pathname是終端設備,則不將該設備分配作爲這個進程的控制終端。
O_NOFOLLOW        ;若pathname是鏈接,則報錯。
O_SYNC            ;同步模式,即每次寫入都要等待寫入操作完成。
O_TRUNC           ;截斷模式,即以可寫模式打開文件後將文件截斷(清空)

上面的常量可以使用”或”運算組合。

mode 是指創建文件時的文件權限,可以使用下列方式代表:
A)8進製表示法:

四位數字,第一位數表示文件的特殊權限(只有root才能賦予這些權限),第二位數字表示文件所有者擁有的權限,第三位數字代表羣組成員擁有的權限,第四位數字代表系統其他用戶擁有的權限,每一位都由幾個表示特定權限的數字相加而成,加了表示某個權限的數字,表示擁有該權限。

第一位數:文件的特殊權限4代表SUID2代表SGID1代表SBIT

第二位數:表示文件所有者擁有的權限:4代表R(讀)2代表W(寫)1代表X(執行).

第三位數:表示羣組成員擁有的權限:4代表R(讀)2代表W(寫)1代表X(執行).

第四位數:表示其他用戶擁有的權限:4代表R(讀)2代表W(寫)1代表X(執行).

舉個例子,0777表示該文件沒有特殊權限,所有用戶(文件所有者、羣組成員、其他用戶)都具有讀、寫、執行權限(7=4+2+1)。

0755表示沒有特殊權限,文件所有者 具有讀、寫、執行權限(7=4+2+1),羣組用戶和其他用戶只擁有讀、執行權限(5=4+1)。

4755表示具有SUID特殊權限,文件所有者 具有讀、寫、執行權限(7=4+2+1),羣組用戶和其他用戶只擁有讀、執行權限(5=4+1)。

B)常量表示法

其實在編寫應用在UNIX/Linux程序的時候,涉及到文件權限時,我們可以用一組常量來代替8進製表示法:
基本格式:S_I<權限><指定對象:文件擁有者/羣組成員/其他用戶>

下面給出了一些常見的常量及釋義:

常量 釋義
S_IRWXU 文件擁有者(User)擁有讀(R)、寫(W)、執行(X) 的權限
S_IRUSR 文件擁有者(User)擁有讀(R) 的權限
S_IWUSR 文件擁有者(User)擁有寫(W) 的權限
S_IXUSR 文件擁有者(User)擁有執行(X) 的權限
S_IRWXG 羣組成員(Group)擁有讀(R)、寫(W)、執行(X) 的權限
S_IRGRP 羣組成員(Group)擁有讀(R) 的權限
S_IWGRP 羣組成員(Group)擁有寫(W) 的權限
S_IXGRP 羣組成員(Group)擁有執行(X) 的權限
S_IRWXO 其他用戶(Other)擁有讀(R)、寫(W)、執行(X) 的權限
S_IROTH 其他用戶(Other)擁有讀(R) 的權限
S_IWOTH 其他用戶(Other)擁有寫(W) 的權限
S_IXOTH 其他用戶(Other)擁有執行(X) 的權限
S_SUID 設置SUID特殊權限
S_SGID 設置SGID特殊權限
S_SVTX 設置SBIT特殊權限

creat 函數用於創建文件。實際上,使用:

int creat(const char *pathname, mode_t mode);

相當於使用:

open(pathname,O_WRONLY|O_CREAT|O_TRUNC,mode);

即以截斷式創建文件並以只寫方式打開文件。

close系統調用比較簡單,它的功能就是要關閉已經打開的文件。它的參數只有一個,即打開的文件的文件描述符。

關於SUID、SGID、SBIT的補充說明:

SUID的意思是在運行被賦予了SUID特殊權限的程序(擁有可執行權限X)時,會暫時將運行着的程序用戶權限提升至文件擁有者的權限。

舉個栗子,Linux系統使用時我們會用sudo命令提權執行一些普通用戶執行不了的操作,在使用sudo命令的提權之前需要用戶輸入密碼確定使用者身份,這就需要訪問/etc/shadow文件來驗證加密過的用戶密碼是否與存儲的一致了。可是這個文件的擁有者是root,權限是0700,除了root用戶之外,其餘用戶不具有查看及修改這個文件的權限,也就是說,以普通用戶身份運行的程序是無法查看這個文件的。實際上,sudo命令是被賦予了SUID特殊權限的,在運行過程中,運行者的權限會暫時提升到文件擁有者的權限(即root),這樣,sudo就可以訪問/etc/shadow文件來驗證密碼了。

SGID的作用跟SUID差不多,區別在於,SUID是將當前用戶權限提升到文件擁有者權限,而SGID是將當前用戶權限提升到羣組成員擁有的權限。

SBIT是針對目錄的,在多用戶環境下,對一個目錄設置了SBIT權限,則當 當前用戶對該目錄擁有執行與寫入權限時(即可以進入該文件夾並寫入文件),自己創建的文件、子目錄只有自己和root用戶纔有權限刪除,這一點非常適合用於文件夾共享的情況下防止誤刪除而導致數據丟失。

下面是一些使用的栗子:

int fd0=open("/tmp/test.txt",O_RDWR);          //讀寫打開/tmp/test.txt
int fd1=open("/tmp",O_RDWR);                   //只讀打開/tmp(目錄)
int fd2=openat(fd1,“test2.txt”,O_WRONLY,S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); //在前面打開的目錄(/tmp)下創建文件test.txt,並賦予權限0755(文件所有者 具有讀、寫、執行權限,羣組用戶和其他用戶只擁有讀、執行權限)。
int fd3=creat("/tmp/test3.txt",S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); //創建文件/tmp/test3.txt,權限0755
close(fd0);//關閉打開的文件fd0
close(fd1);
close(fd2);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章