fcntl.h

fcntl.h,是unix標準中通用的頭檔案,其中包含的相關函式有 open,fcntl,shutdown,unlink,fclose等!

基本介紹

  • 中文名:fcntl.h
  • 定義:open,fcntl函式原型
  • 表頭檔案:#include<unistd.h>
  • 旗標:避免一些系統安全問題
簡介,表頭檔案,

簡介

fcntl.h與unistd.h
fcntl.h定義了很多宏和open,fcntl函式原型
unistd.h定義了更多的函式原型
close(關閉檔案)
表頭檔案#include<unistd.h>
定義函式int close(int fd);
函式說明當使用完檔案後若已不再需要則可使用close()關閉該檔案,二
close()會讓數據寫回磁碟,並釋放該檔案所占用的資源。參數fd為
先前由open()或creat()所返回的檔案描述詞
返回值若檔案順利關閉則返回0,發生錯誤時返回-1。
錯誤代碼EBADF 參數fd 非有效的檔案描述詞或該檔案已關閉。
附加說明雖然在進程結束時,系統會自動關閉已打開的檔案,但仍建議自行
關閉檔案,並確實檢查返回值。(系統可能有緩衝,在適當的時候才寫入,特別是NFS網路檔案系統)
open(打開檔案)

表頭檔案

#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);
函式說明參數pathname 指向欲打開的檔案路徑字元串。下列是參數flags 所能使用的旗標:
O_RDONLY 以唯讀方式打開檔案
O_WRONLY 以只寫方式打開檔案
O_RDWR 以可讀寫方式打開檔案。上述三種旗標是互斥的,也就是不可同時使用,
但可與下列的旗標利用OR(|)運算符組合。
O_CREAT 若欲打開的檔案不存在則自動建立該檔案。
O_EXCL 如果O_CREAT 也被設定,此指令會去檢查檔案是否存在。檔案若不存在則建立該檔案,否則將導致打開檔案錯誤。此外,若
O_CREAT與O_EXCL同時設定,並且欲打開的檔案為符號連線,則會打開檔案失敗。
O_NOCTTY 如果欲打開的檔案為終端機設備時,則不會將該終端機當成進程控制終端機。
O_TRUNC 若檔案存在並且以可寫的方式打開時,此旗標會令檔案長度清為0,而原來存於該檔案的資料也會消失。
O_APPEND 當讀寫檔案時會從檔案尾開始移動,也就是所寫入的數據會以附加的方式加入到檔案後面。
O_NONBLOCK 以不可阻斷的方式打開檔案,也就是無論有無數據讀取或等待,都會立即返回進程之中。
O_NDELAY 同O_NONBLOCK。
O_SYNC 以同步的方式打開檔案。
O_NOFOLLOW 如果參數pathname 所指的檔案為一符號連線,則會令打開檔案失敗。
O_DIRECTORY 如果參數pathname 所指的檔案並非為一目錄,則會令打開檔案失敗。
O_NOATIME 從linux 2.6.8核心開始,讀檔案不更新檔案最後訪問時間
此為Linux2.2以後特有的旗標,以避免一些系統安全問題。參數mode 則有下列數種組合,只有在建立新檔案時才會生效,此外真正建檔案時的許可權會受到umask值所影響,因此該檔案許可權應該為(mode-umaks)。
The argument mode specifies the permissions to use in case a new file is created. It is modified by the pro-cess's umask in the usual way: the permissions of the created file are (mode & ~umask). Note that this mode only applies to future accesses of the newly created file; the open call that creates a read-only file may well return a read/write file descriptor.
S_IRWXU00700 許可權,代表該檔案所有者具有可讀、可寫及可執行的許可權。
S_IRUSR 或S_IREAD,00400許可權,代表該檔案所有者具有可讀取的許可權。
S_IWUSR 或S_IWRITE,00200 許可權,代表該檔案所有者具有可寫入的許可權。
S_IXUSR 或S_IEXEC,00100 許可權,代表該檔案所有者具有可執行的許可權。
S_IRWXG 00070許可權,代表該檔案用戶組具有可讀、可寫及可執行的許可權。
S_IRGRP 00040 許可權,代表該檔案用戶組具有可讀的許可權。
S_IWGRP 00020許可權,代表該檔案用戶組具有可寫入的許可權。
S_IXGRP 00010 許可權,代表該檔案用戶組具有可執行的許可權。
S_IRWXO 00007許可權,代表其他用戶具有可讀、可寫及可執行的許可權。
S_IROTH 00004 許可權,代表其他用戶具有可讀的許可權
S_IWOTH 00002許可權,代表其他用戶具有可寫入的許可權。
S_IXOTH 00001 許可權,代表其他用戶具有可執行的許可權。
返回值若所有欲核查的許可權都通過了檢查則返回0 值,表示成功,只要有一個許可權被禁止則返回-1。
錯誤代碼EEXIST 參數pathname 所指的檔案已存在,卻使用了O_CREAT和O_EXCL旗標
EACCESS 參數pathname所指的檔案不符合所要求測試的許可權。
EROFS 欲測試寫入許可權的檔案存在於唯讀檔案系統內。
EFAULT 參數pathname指針超出可存取記憶體空間。
EINVAL 參數mode 不正確。
ENAMETOOLONG 參數pathname太長。
ENOTDIR 參數pathname不是目錄。
ENOMEM 核心記憶體不足。
ELOOP 參數pathname有過多符號連線問題。
EIO I/O 存取錯誤。
附加說明使用access()作用戶認證方面的判斷要特別小心,例如在access()後再作open()空檔案可能會造成系統安全上的問題。
範例
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
main()
{
int fd,size;
char s [ ]=”Linux Programmer!\n”,buffer[80];
fd=open(“/tmp/temp”,O_WRONLY|O_CREAT);
write(fd,s,sizeof(s));
close(fd);
fd=open(“/tmp/temp”,O_RDONLY);
size=read(fd,buffer,sizeof(buffer));
close(fd);
printf(“%s”,buffer);
}
執行Linux Programmer!
creat(建立檔案)
表頭檔案
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
定義函式int creat(const char * pathname, mode_tmode);
函式說明參數pathname指向欲建立的檔案路徑字元串。Creat()相當於使用下列的調用方式調用open(),
open(const char * pathname ,(O_CREAT|O_WRONLY|O_TRUNC));
錯誤代碼關於參數mode請參考open()函式。
返回值creat()會返回新的檔案描述詞,若有錯誤發生則會返回-1,並把錯
誤代碼設給errno。
EEXIST 參數pathname所指的檔案已存在。
EACCESS 參數pathname 所指定的檔案不符合所要求測試的許可權
EROFS 欲打開寫入許可權的檔案存在於唯讀檔案系統內
EFAULT 參數pathname 指針超出可存取的記憶體空間
EINVAL 參數mode 不正確。
ENAMETOOLONG 參數pathname太長。
ENOTDIR 參數pathname為一目錄
ENOMEM 核心記憶體不足
ELOOP 參數pathname有過多符號連線問題。
EMFILE 已達到進程可同時打開的檔案數上限
ENFILE 已達到系統可同時打開的檔案數上限
附加說明creat()無法建立特別的裝置檔案,如果需要請使用mkmod()。
dup(複製檔案描述詞
表頭檔案#include<unistd.h>
定義函式int dup (int oldfd);
函式說明dup()用來複製參數oldfd所指的檔案描述詞,並將它返回。此新的檔案描述詞和參數oldfd指的是同一個檔案,共享所有的鎖定、讀寫位置和各項許可權或旗標。例如,當利用lseek()對某個檔案描述詞作用時,另一個檔案描述詞的讀寫位置也會隨著改變。不過,檔案描述詞之間並不共享close-on-exec旗標。
返回值當複製成功時,則返回最小及尚未使用的檔案描述詞。若有錯誤則
返回-1,errno會存放錯誤代碼。錯誤代碼EBADF參數fd非有效的文
件描述詞,或該檔案已關閉。
表頭檔案#include<unistd.h>
定義函式int dup2(int odlfd,int newfd);
函式說明dup2()用來複製參數oldfd所指的檔案描述詞,並將它拷貝至參數newfd後一塊返回。若參數newfd為一已打開的檔案描述詞,則newfd所指的檔案會先被關閉。dup2()所複製的檔案描述詞,與原來的檔案描述詞共享各種檔案狀態,詳情可參考dup()。
返回值當複製成功時,則返回最小及尚未使用的檔案描述詞。若有錯誤則返回-1,errno會存放錯誤代碼
附加說明dup2()相當於調用fcntl(oldfd,F_DUPFD,newfd);請參考fcntl()。
錯誤代碼EBADF 參數fd 非有效的檔案描述詞,或該檔案已關閉
fcntl(檔案描述詞操作)
相關函式open,flock
表頭檔案#include<unistd.h>
#include<fcntl.h>
定義函式int fcntl(int fd , int cmd);
int fcntl(int fd,int cmd,long arg);
int fcntl(int fd,int cmd,struct flock * lock);
函式說明fcntl()用來操作檔案描述詞的一些特性。參數fd代表欲設定的檔案
描述詞,參數cmd代表欲操作的指令。
有以下幾種情況:
F_DUPFD用來查找大於或等於參數arg的最小且仍未使用的檔案描述
詞,並且複製參數fd的檔案描述詞。執行成功則返回新複製的檔案
描述詞。請參考dup2()。F_GETFD取得close-on-exec旗標。若此旗
標的FD_CLOEXEC位為0,代表在調用exec()相關函式時檔案將不會關
閉。
F_SETFD 設定close-on-exec 旗標。該旗標以參數arg 的
FD_CLOEXEC位決定。
F_GETFL 取得檔案描述詞狀態旗標,此旗標為open()的參數
flags。
F_SETFL 設定檔案描述詞狀態旗標,參數arg為新旗標,但只允許
O_APPEND、O_NONBLOCK和O_ASYNC位的改變,其他位的改變將不受影
響。
F_GETLK 取得檔案鎖定的狀態。
F_SETLK 設定檔案鎖定的狀態。此時flock 結構的l_type 值必須是
F_RDLCK、F_WRLCK或F_UNLCK。如果無法建立鎖定,則返回-1,錯誤
代碼為EACCES 或EAGAIN。
F_SETLKW F_SETLK 作用相同,但是無法建立鎖定時,此調用會一直
等到鎖定動作成功為止。若在等待鎖定的過程中被信號中斷時,會
立即返回-1,錯誤代碼為EINTR。參數lock指針為flock 結構指針,
定義如下
struct flock
{
short int l_type; /* 鎖定的狀態*/
short int l_whence;/*決定l_start位置*/
off_t l_start; /*鎖定區域的開頭位置*/
off_t l_len; /*鎖定區域的大小*/
pid_t l_pid; /*鎖定動作的進程*/
};
l_type 有三種狀態:
F_RDLCK 建立一個供讀取用的鎖定
F_WRLCK 建立一個供寫入用的鎖定
F_UNLCK 刪除之前建立的鎖定
l_whence 也有三種方式:
SEEK_SET 以檔案開頭為鎖定的起始位置。
SEEK_CUR 以目前檔案讀寫位置為鎖定的起始位置
SEEK_END 以檔案結尾為鎖定的起始位置。
返回值成功則返回0,若有錯誤則返回-1,錯誤原因存於errno.
flock(鎖定檔案或解除鎖定)
相關函式open,fcntl
表頭檔案#include<sys/file.h>
定義函式int flock(int fd,int operation);
函式說明flock()會依參數operation所指定的方式對參數fd所指的檔案做各
種鎖定或解除鎖定的動作。此函式只能鎖定整個檔案,無法鎖定文
件的某一區域。
參數operation有下列四種情況:
LOCK_SH 建立共享鎖定。多個進程可同時對同一個檔案作共享鎖
定。
LOCK_EX 建立互斥鎖定。一個檔案同時只有一個互斥鎖定。
LOCK_UN 解除檔案鎖定狀態。
LOCK_NB 無法建立鎖定時,此操作可不被阻斷,馬上返回進程。通
常與LOCK_SH或LOCK_EX 做OR(|)組合。
單一檔案無法同時建立共享鎖定和互斥鎖定,而當使用dup()或fork
()時檔案描述詞不會繼承此種鎖定。
返回值返回0表示成功,若有錯誤則返回-1,錯誤代碼存於errno。
fsync(將緩衝區數據寫回磁碟)
相關函式sync
表頭檔案#include<unistd.h>
定義函式int fsync(int fd);
函式說明fsync()負責將參數fd所指的檔案數據,由系統緩衝區寫回磁碟,以
確保數據同步。
返回值成功則返回0,失敗返回-1,errno為錯誤代碼。
lseek(移動檔案的讀寫位置)
表頭檔案#include<sys/types.h>
#include<unistd.h>
定義函式off_t lseek(int fildes,off_t offset ,int whence);
函式說明每一個已打開的檔案都有一個讀寫位置,當打開檔案時通常其讀寫
位置是指向檔案開頭,若是以附加的方式打開檔案(如O_APPEND),
則讀寫位置會指向檔案尾。當read()或write()時,讀寫位置會隨之
增加,lseek()便是用來控制該檔案的讀寫位置。參數fildes 為已
打開的檔案描述詞,參數offset 為根據參數whence來移動讀寫位置
的位移數。
參數whence為下列其中一種:
SEEK_SET 參數offset即為新的讀寫位置。
SEEK_CUR 以目前的讀寫位置往後增加offset個位移量。
SEEK_END 將讀寫位置指向檔案尾後再增加offset個位移量。
當whence 值為SEEK_CUR 或SEEK_END時,參數offet允許負值的出
現。
下列是教特別的使用方式:
1) 欲將讀寫位置移到檔案開頭時:lseek(int
fildes,0,SEEK_SET);
2) 欲將讀寫位置移到檔案尾時:lseek(int fildes,
0,SEEK_END);
3) 想要取得檔案位置時:lseek(int fildes,0,SEEK_CUR);
返回值當調用成功時則返回讀寫位置,也就是距離檔案開頭多少個
位元組。若有錯誤則返回-1,errno 會存放錯誤代碼
附加說明Linux系統不允許lseek()對tty裝置作用,此項動作會令lseek
()返回ESPIPE。
範例參考本函式說明
read(由已打開的檔案讀取數據)
定義函式ssize_t read(int fd,void * buf ,size_t count);
函式說明read()會把參數fd 所指的檔案傳送count個位元組到buf指針所指的內
存中。若參數count為0,則read()不會有作用並返回0。返回值為實
際讀取到的位元組數,如果返回0,表示已到達檔案尾或是無可讀取的
數據,此外檔案讀寫位置會隨讀取到的位元組移動。
附加說明如果順利read()會返回實際讀到的位元組數,最好能將返回值與參數
count 作比較,若返回的位元組數比要求讀取的位元組數少,則有可能
讀到了檔案尾、從管道(pipe)或終端機讀取,或者是read()被信號
中斷了讀取動作。當有錯誤發生時則返回-1,錯誤代碼存入errno
中,而檔案讀寫位置則無法預期。
錯誤代碼EINTR 此調用被信號所中斷。
EAGAIN 當使用不可阻斷I/O 時(O_NONBLOCK),若無數據可讀取則
返回此值。
EBADF 參數fd 非有效的檔案描述詞,或該檔案已關閉。
範例參考open()。
sync(將緩衝區數據寫回磁碟)
相關函式fsync
表頭檔案#include<unistd.h>
定義函式int sync(void)
函式說明sync()負責將系統緩衝區數據寫回磁碟,以確保數據同步。
返回值返回0。
write(將數據寫入已打開的檔案內)
定義函式ssize_t write (int fd,const void * buf,size_t count);
函式說明write()會把參數buf所指的記憶體寫入count個位元組到參數fd所指的文
件內。當然,檔案讀寫位置也會隨之移動。
返回值如果順利write()會返回實際寫入的位元組數。當有錯誤發生時則返
回-1,錯誤代碼存入errno中。
錯誤代碼EINTR 此調用被信號所中斷。
EAGAIN 當使用不可阻斷I/O 時(O_NONBLOCK),若無數據可讀取則
返回此值。
EADF 參數fd非有效的檔案描述詞,或該檔案已關閉。
範例請參考open()。
Fork
傳統方式下,Fork創建一個子進程,並為子進程創建一個父進程地址空間的拷貝。然而,由於許多子進程在創建之後通常馬上會執行系統調用exec,所以父進程地址空間的複製可能沒有必要,從而造成效率和記憶體的極大浪費。因此,就產生了一種稱為“寫時複製”的技術。
現在是寫時複製
寫 時複製允許子進程與父進程在開始時共享同一頁面。但這些頁面被標記為“寫時複製”,即如果任何一個進程需要對頁進行寫操作,就會創建這個共享頁的拷貝。例 如,假設子進程試圖修改含有部分棧的頁,且作業系統能夠識別出該頁為寫時複製頁,則作業系統就會創建該頁的一個拷貝,並將它映射的子進程的地址空間里。這 樣,子進程修改的就是其複製的頁,而不是父進程的頁。採用寫時複製技術,只有被進程所修改的頁才會複製,而所有非修改的頁可為父進程和子進程共享。注意, 並不是所有的頁都標記為寫時複製,只有可能修改的頁才需要標記為寫時複製,對不能修改的頁,如代碼頁,可謂父進程和子進程所共享。
Vfork(Virtual memory fork)
Vfork不 同於寫時複製的fork。對於vfork,父進程會掛起,以確保子進程先運行。子進程使用父進程的地址空間。由於vfork不使用寫時複製,因此如果子進 程修改地址空間的任何頁,這些修改在父進程重啟時都是可見的。所以,vfork必須小心使用,以確保子進程不會修改父進程地址空間。Vfork主要用於 在進程創建後立即調用exec的情況,這樣既沒有出現複製頁,也不會修改父進程的地址空間,所以是一種很有效的進程創建方法。
char *getcwd(char *buf, size_t size);
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
/*
* if limits.h no define PATH_MAX,I define.
*/
#ifndef PATH_MAX
#define PATH_MAX 255
#endif
int main(){
char workdir[PATH_MAX];
if(!getcwd(workdir,PATH_MAX))
perror("couldn't get current work directory!\n");
else
printf("workdir = %s\n",workdir);
return 0;
}
long pathconf(char *path, int name);
int chdir(const char* path);
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <stdlib.h>
int main(){
char *workdir;
long path_max;
if((path_max = pathconf("/",_PC_PATH_MAX)) == -1){
perror("couldn't get _PC_PATH_MAX!\n");
return -1;
}
printf("path_max is %d\n",path_max);
if((workdir = (char *)malloc(path_max)) == NULL){
perror("couldn't allocate memory for the workdir!\n");
return -1;
}
if(getcwd(workdir,path_max) == NULL){
perror("couldn't get current work directory!\n");
return -1;
}
printf("current dir is %s\n",workdir);
if(chdir("..") == -1){
perror("change directory error!\n");
return -1;
}
if(getcwd(workdir,path_max) == NULL){
perror("couldn't get current work directory!\n");
return -1;
}
printf("current dir is %s\n",workdir);
free(workdir);
return 0;
}
int rmdir(const char * pathname);
int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);
int unlink(const char *pathname);
int link(const char *oldpath, const char *newpath);
int symlink(const char *oldpath, const char *newpath); //Symbolic links軟連線
char * ttyname(int fd);
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc,char *argv[]){
char * tty_out;
if( (tty_out = ttyname(STDOUT_FILENO) ) == NULL){
perror("cannot get tty name\n");
return -1;
}
printf("STDOUT_FILENO tty name is :%s\n",tty_out);
return 0;
}
void usleep(unsigned long usec);毫秒
pid_t getpid(void);
pid_t getppid(void);
uid_t getuid(void);
uid_t geteuid(void);
gid_t getgid(void);
gid_t getegid(void);
int execl(const char *path, const char *arg, ...);int execlp(const char *file, const char *arg, ...);int execle(const char *path, const char *arg, ..., char *const envp[]);int execv(const char *path, char *const argv[]);int execvp(const char *file, char *const argv[]);int execve(const char *path, char *const argv[], char *const envp[]);pid_t setsid(void);int lockf(int fd, int cmd, off_t len);unsigned int alarm(unsigned int seconds);int pipe(int pipefd[2]);

相關詞條

熱門詞條

聯絡我們