系統調用
系統調用可以操作內核,是外部程序和內核層交互的接口,但不能過於頻繁的調用,否則效率極低。
time命令可以查看用戶層及其內核層的執行時間。
文件和目錄
在Linux/Unix中,幾乎一切都可以被看成文件。
因此,系統調用函數open/close/read/write/ioctl幾乎可以通用。
在Unix的系統調用中,打開/創建一個文件會產生一個文件表,這個文件表用非負整數代表,這個非負整數叫文件描述符。系統默認佔有0/1/2,因此文件描述符從3開始。文件描述符關閉後可以循環使用。
Unix系統調用之 - 文件相關函數
文件的信息都記錄在文件表中
(open)
利用文件描述符可以進行各種操作(read/write)
fcntl函數可以用於操控文件的狀態和文件鎖定,格式
int fcntl(int fd,int cmd,...)
cmd常用的有:()裏邊是第三個參數
F_DUPFD(long) 複製文件描述符,但不會強制關閉
F_GETFL(void) 取文件的訪問模式和文件狀態
F_SETFL(long) 不包括 創建狀態
F_SERLK/F_SETLKW/F_GETLK 文件鎖相關
實例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(){
int fd=open("a.txt",O_RDWR|O_CREAT|O_APPEND,0666);
if(fd==-1) perror("open"),exit(-1);
//複製文件描述符,如果沒有使用返回參數值,如果使用了,返回比參數大的第一個沒有使用的值
int fd2 = fcntl(fd,F_DUPFD,5);//返回5
int fd3 = fcntl(fd,F_DUPFD,5);//返回6,不是4
printf("fd=%d,fd2=%d,fd3=%d\n",fd,fd2,fd3);
int flags = fcntl(fd,F_GETFL);
printf("flags=%d\n",flags);
if((flags&3) == 2) printf("RDWR\n");
if((flags&3) == 1) printf("WRONLY\n");
if((flags&3) == 0) printf("RDONLY\n");
if(flags & O_APPEND) printf("Append\n");
//flags不記錄創建標誌O_CREAT/TRUNC/EXCL
if(flags & O_CREAT) printf("create\n");
//訪問權限是不能修改
fcntl(fd,F_SETFL,O_WRONLY);
flags = fcntl(fd,F_GETFL);
printf("flags=%d\n",flags);
if((flags&3) == 2) printf("RDWR\n");
if((flags&3) == 1) printf("WRONLY\n");
if((flags&3) == 0) printf("RDONLY\n");
if(flags & O_APPEND) printf("Append\n");
close(fd);
return 0;
}
文件鎖可以控制多個進程對文件的同時操作,但不能防止人爲讀寫文件(vi/gedit/...)。可以控制文件的位置,也就是可以鎖定文件的某部分。結構體flock用於記錄鎖的信息。
struct flock{
short l_type; //鎖的類型 包括讀鎖/寫鎖/解鎖
short l_whence;//鎖的起始位置參照
int l_start; //偏移量
int l_len; //鎖定長度
pid_t l_pid;//上鎖進程id,一般給-1即可
};
l_whence 使用seek的參數 SEEK_SET/SEEK_CUR/SEEK_END,與l_start參數一起決定開始鎖定的位置。
讀寫鎖:
F_RDLCK 讀鎖
讀鎖其實鎖定的是其他的寫進程,不鎖定其他的讀進程。讀文件(不能寫)的進程使用,是共享鎖。
F_WRLCK 寫鎖
寫鎖鎖定其他所有進程。寫文件時使用,是獨佔鎖
鎖其實只是作爲 read/write的條件,而不是真正鎖定文件。能上鎖分支就可以讀寫,不能上鎖分支不要讀寫
上鎖時可以指定爲等待其它鎖結束後再鎖定方式(阻塞),fcntl(fd,F_SETLKW,&lock) 即可。
F_GETLK 不是加鎖,也不是取鎖,是測試能否加鎖。
如果能加,把lock的l_type變成F_UNLCK,但不真正加鎖。如果不能加,把當前的鎖放入lock中返回。
實例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main(){
int fd = open("a.txt",O_RDWR);
if(fd==-1) perror("open"),exit(-1);
struct flock rlock;
rlock.l_type = F_RDLCK;
rlock.l_whence = SEEK_SET;
rlock.l_start = 0;
rlock.l_len = 20;
rlock.l_pid = -1;
int res = fcntl(fd,F_GETLK,&rlock);
printf("rdlk=%d,wrlk=%d,unlk=%d\n",F_RDLCK,F_WRLCK,F_UNLCK);
printf("type=%d,pid=%d\n",rlock.l_type,rlock.l_pid);
if(res == -1) perror("GetLock"),exit(-1);
if(rlock.l_pid == -1){//常用pid判斷
printf("可以加讀鎖\n");
}else{
printf("不可以加讀鎖\n");
}
rlock.l_type = F_WRLCK;
res = fcntl(fd,F_GETLK,&rlock);
if(res == -1) perror("GetLock"),exit(-1);
if(rlock.l_pid == -1){//常用pid判斷
printf("可以加寫鎖\n");
}else{
printf("不可以加寫鎖\n");
}
printf("type=%d,pid=%d\n",rlock.l_type,rlock.l_pid);
close(fd);
return 0;
}