sigaction 函数,sigemptyset()函数,fcntl()函数,isatty()函数
第一個函數:使用 sigaction函數:
?signal 函數的使用方法簡單,但并不屬于POSIX標準,在各類UNIX平臺上的實現不盡相同,因此其用途受
到了一定的限制。而 POSIX標準定義的信號處理接口是sigaction函數,其接口頭文件及原型如下:
?#include <signal.h>
?int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
?◆ signum:要操作的信號。
?◆ act:要設置的對信號的新處理方式。
?◆ oldact:原來對信號的處理方式。
?◆ 返回值:0表示成功,-1表示有錯誤發生。
?struct sigaction 類型用來描述對信號的處理,定義如下:
struct sigaction{void (*sa_handler)(int);void (*sa_sigaction)(int, siginfo_t *, void *);sigset_t sa_mask;int sa_flags;void (*sa_restorer)(void);};?在這個結構體中,成員 sa_handler是一個函數指針,其含義與signal函數中的信號處理函數類似。成員
sa_sigaction 則是另一個信號處理函數,它有三個參數,可以獲得關于信號的更詳細的信息。當sa_flags成員的值
包含了 SA_SIGINFO標志時,系統將使用sa_sigaction函數作為信號處理函數,否則使用sa_handler作為信號處理
函數。在某些系統中,成員 sa_handler與sa_sigaction被放在聯合體中,因此使用時不要同時設置。
sa_mask 成員用來指定在信號處理函數執行期間需要被屏蔽的信號,特別是當某個信號被處理時,它自身會被
自動放入進程的信號掩碼,因此在信號處理函數執行期間這個信號不會再度發生。
?sa_flags 成員用于指定信號處理的行為,它可以是一下值的“按位或”組合。
?◆ SA_RESTART:使被信號打斷的系統調用自動重新發起。
?◆ SA_NOCLDSTOP:使父進程在它的子進程暫停或繼續運行時不會收到SIGCHLD信號。
?◆ SA_NOCLDWAIT:使父進程在它的子進程退出時不會收到SIGCHLD信號,這時子進程如果退出也不會成為僵
尸進程。
?◆ SA_NODEFER:使對信號的屏蔽無效,即在信號處理函數執行期間仍能發出這個信號。
?◆ SA_RESETHAND:信號處理之后重新設置為默認的處理方式。
?◆ SA_SIGINFO:使用sa_sigaction成員而不是sa_handler作為信號處理函數。
?re_restorer 成員則是一個已經廢棄的數據域,不要使用。
?下面用一個例程來說明 sigaction函數的使用,代碼如下:
第二個函數:sigemptyset()函數:初始化信號集?
相關函數:sigaddset, sigfillset, sigdelset, sigismember
頭文件:#include <signal.h>
定義函數:int sigemptyset(sigset_t *set);
函數說明:sigemptyset()用來將參數set信號集初始化并清空.
返回值:執行成功則返回0,如果有錯誤則返回-1.
錯誤代碼:EFAULT參數set指針地址無法存取。
?
第三個函數:fcntl()函數
功能描述:根據文件描述詞來操作文件的特性。
用法: ??
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
參數: ??
fd:文件描述詞。
cmd:操作命令。
arg:供命令使用的參數。
lock:同上??
F_SETFL的使用:fcntl(fd, F_SETFL, 0)
1、獲取文件的flags,即open函數的第二個參數:
? ? ? ?flags = fcntl(fd,F_GETFL,0);
2、設置文件的flags:
? ? ? fcntl(fd,F_SETFL,flags);
3、增加文件的某個flags,比如文件是阻塞的,想設置成非阻塞:
? ? ? ?flags = fcntl(fd,F_GETFL,0);
? ? ? ?flags |= O_NONBLOCK;
? ? ? fcntl(fd,F_SETFL,flags);
4、取消文件的某個flags,比如文件是非阻塞的,想設置成為阻塞:
? ? ? flags = fcntl(fd,F_GETFL,0);
? ? ? flags &= ~O_NONBLOCK;
? ? ? fcntl(fd,F_SETFL,flags);
有以下操作命令可供使用
一. ?F_DUPFD:復制文件描述詞 。
二. ?FD_CLOEXEC:設置close-on-exec標志。如果FD_CLOEXEC位是0,執行execve的過程中,文件保持打開。反之則關閉。
三. ??F_GETFD:讀取文件描述詞標志。
四. ??F_SETFD:設置文件描述詞標志。
五. ?F_GETFL:讀取文件狀態標志。
六. ??F_SETFL:設置文件狀態標志。
其中O_RDONLY,O_WRONLY,O_RDWR,O_CREAT, ?O_EXCL,O_NOCTTY和O_TRUNC不受影響,可以更改的標志有O_APPEND,O_ASYNC,O_DIRECT,O_NOATIME和O_NONBLOCK。
七. ?F_GETLK, F_SETLK和F_SETLKW:獲取,釋放或測試記錄鎖,使用到的參數是以下結構體指針:
F_SETLK:在指定的字節范圍獲取鎖(F_RDLCK, F_WRLCK)或者釋放鎖(F_UNLCK)。如果與另一個進程的鎖操作發生沖突,返回-1并將errno設置為EACCES或EAGAIN。 ????????
F_SETLKW:行為如同F_SETLK,除了不能獲取鎖時會睡眠等待外。如果在等待的過程中接收到信號,會立即返回并將errno置為EINTR。
F_GETLK:獲取文件鎖信息。 F_UNLCK:釋放文件鎖。
為了設置讀鎖,文件必須以讀的方式打開。為了設置寫鎖,文件必須以寫的方式打開。為了設置讀寫鎖,文件必須以讀寫的方式打開。
八. 信號管理
F_GETOWN, F_SETOWN, F_GETSIG 和 F_SETSIG被用于IO可獲取的信號。
F_GETOWN:獲取當前在文件描述詞fd上接收到SIGIO或SIGURG事件信號的進程或進程組標識 。
F_SETOWN:設置將要在文件描述詞fd上接收SIGIO或SIGURG事件信號的進程或進程組標識 。
F_GETSIG:獲取標識輸入輸出可進行的信號。
F_SETSIG:設置標識輸入輸出可進行的信號。
使用以上命令,大部分時間程序無須使用select()或poll()即可實現完整的異步I/O。?
九. 租約( Leases)
F_SETLEASE 和 F_GETLEASE被用于當前進程在文件上的租約。文件租約提供當一個進程試圖打開或折斷文件內容時,擁有文件租約的進程將會被通告的機制。
F_SETLEASE:根據以下符號值設置或者刪除文件租約
1.F_RDLCK設置讀租約,當文件由另一個進程以寫的方式打開或折斷內容時,擁有租約的當前進程會被通告。
2.F_WRLCK設置寫租約,當文件由另一個進程以讀或以寫的方式打開或折斷內容時,擁有租約的當前進程會被通告。
3.F_UNLCK刪除文件租約。
F_GETLEASE:獲取租約類型。
十.文件或目錄改變通告
(linux 2.4以上)當fd索引的目錄或目錄中所包含的某一文件發生變化時,將會向進程發出通告。arg參數指定的通告事件有以下,兩個或多個值可以通過或運算組合。
1.DN_ACCESS 文件被訪問 (read, pread, readv)
2.DN_MODIFY 文件被修改(write, pwrite,writev, truncate, ftruncate)
3.DN_CREATE 文件被建立(open, creat, mknod, mkdir, link, symlink, rename)
4.DN_DELETE 文件被刪除(unlink, rmdir)
5.DN_RENAME 文件被重命名(rename)
6.DN_ATTRIB 文件屬性被改變(chown, chmod, utime[s])
返回說明: ??
成功執行時,對于不同的操作,有不同的返回值
F_DUPFD: 新文件描述詞
F_GETFD: ?標志值
F_GETFL: ?標志值
F_GETOWN: 文件描述詞屬主
F_GETSIG: 讀寫變得可行時將要發送的通告信號,或者0對于傳統的SIGIO行為
對于其它命令返回0。失敗返回-1,errno被設為以下的某個值 。 ?
EACCES/EAGAIN: 操作不被允許,尚未可行
EBADF: 文件描述詞無效
EDEADLK: 探測到可能會發生死鎖
EFAULT: 鎖操作發生在可訪問的地址空間外
EINTR: 操作被信號中斷
EINVAL: 參數無效
EMFILE: 進程已超出文件的最大可使用范圍
ENOLCK: 鎖已被用盡
EPERM:權能不允許
struct flock {
?????????????short l_type; /* 鎖類型: F_RDLCK, F_WRLCK, F_UNLCK */
?????????????short l_whence; /* l_start字段參照點:SEEK_SET(文件頭), SEEK_CUR(文件當前位置), SEEK_END(文件尾) */
?????????????off_t l_start; /* 相對于l_whence字段的偏移量*/
?????????????off_t l_len; /* 需要鎖定的長度 */
?????????????pid_t l_pid; /* 當前獲得文件鎖的進程標識(F_GETLK)*/
};?
linux文件設備與I/O:fcntl函數
2009年05月07日 星期四14:24
可以用fcntl 函數改變一個已打開的文件的屬性,可以重新設置讀、寫、追加、非阻塞等標志(這些標志稱為File StatusFlag),而不必重新open文件。
#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);
這個函數和open 一樣,也是用可變參數實現的,可變參數的類型和個數取決于前面的cmd參數。
針對第2個參數,int cmd fcntl函數有五種功能:
? 復制一個現存的描述符(cmd=F_DUPFD) ???。
? 獲得/設置文件描述符標記(cmd=F_GETFD或F_SETFD) ??。
? 獲得/設置文件狀態標志(cmd=F_GETFL或F_SETFL)。
? 獲得/設置異步I/O有權(cmd=F_GETOWN或F_SETOWN)。
? 獲得/設置記錄鎖(cmd=F_GETLK,F_SETLK或F_SETLKW)。
?
我們將涉及與進程表項中各文件描述符相關聯的文件描述符標志,以及每個文件表項中的文件狀態標志,
一~復制文件描述符
? F_DUPFD 復制文件描述符filedes,新文件描述符作為函數值返回。它是尚未打開的各
描述符中大于或等于第三個參數值(取為整型值)中各值的最小值。新描述符與filedes共享同
一文件表項。但是,新描述符有它自己的一套文件描述符標志,其F D _ C L O E X E C
文件描述符標志則被清除。
? F_GETFD 對應于filedes的文件描述符標志作為函數值返回。當前只定義了一個文件描
述符標志FD_CLOEXEC。
? F_SETFD 對于filedes設置文件描述符標志。新標志值按第三個參數(取為整型值)設置。
應當了解很多現存的涉及文件描述符標志的程序并不使用常數 F D _ C L O E X E C,而是將此
標志設置為0(系統默認,在exec時不關閉)或1(在exec時關閉)。
?
二~文件描述符號,套接口屬性相關
? F_GETFL 對應于filedes的文件狀態標志作為函數值返回。在說明open函數時,已說明
了文件狀態標志 ??不幸的是,三個存取方式標志(O_RDONLY,O_WRONLY,以及O_RDWR)并不各占1位。(正
如前述,這三種標志的值各是0、1和2,由于歷史原因。這三種值互斥 — 一個文件只能有這
三種值之一。 )因此首先必須用屏蔽字O_ACCMODE相與 取得存取方式位,然后將結果與這三種值
相比較。
? F_SETFL 將文件狀態標志設置為第三個參數的值(取為整型值)。 可以更改的幾個標志是:
O_APPEND,O_NONBLOCK,O_SYNC和O_ASYNC。
fcntl的文件狀態標志共有7個,O_RDONLY,O_WRONLY,O_RDWR,O_APPEND,O_NONBLOCK,O_SYNC和O_ASYNC
三~信號驅動I/O ,帶外數據,設置套接口接受信號的屬主
SIGIO,跟信號驅動I/O有關
SIGURG, 和接受帶外數據有關
? F_GETOWN 取當前接收SIGIO和SIGURG信號的進程ID或進程組ID。12.6.2節將論述這
兩種4.3+BSD異步I/O信號。
? F_SETOWN 設置接收SIGIO和SIGURG信號的進程ID或進程組ID。正的arg指定一個進
程ID,負的arg表示等于arg絕對值的一個進程組ID。
?
下面的例子使用F_GETFL和F_SETFL這兩種fcntl命令改變STDIN_FILENO的屬性,上O_NONBLOCK選項,實現非阻塞讀終端的功能。
用fcntl改變File Status Flag
#include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdlib.h> #define MSG_TRY "try again\n" int main(void) { char buf[10]; int n; int flags; flags = fcntl(STDIN_FILENO, F_GETFL); flags |= O_NONBLOCK; if (fcntl(STDIN_FILENO, F_SETFL, flags) == -1){ perror("fcntl"); exit(1); } tryagain: n = read(STDIN_FILENO, buf, 10); if (n < 0) { if (errno == EAGAIN) { sleep(1); write(STDOUT_FILENO, MSG_TRY,strlen(MSG_TRY)); goto tryagain;} perror("read stdin"); exit(1);} write(STDOUT_FILENO, buf, n); return 0; }第四個函數:int isatty(int desc);
(1)主要功能:是檢查設備類型 , 判斷文件描述詞是否是為終端機。
? ? ?返回值:如果參數desc所代表的文件描述詞為一終端機則返回1,否則返回0。
(2)isatty(STDIN_FILENO)
STDIN_FILENO的作用及與stdin 的作用和區別:
1.STDIN_FILENO的作用
? STDIN_FILENO屬于系統API接口庫,其聲明為 int 型,是一個打開文件句柄,對應的函數主要包括 open/read/write/close 等系統級調用。
? 操作系統一級提供的文件API都是以文件描述符來表示文件。STDIN_FILENO就是標準輸入設備(一般是鍵盤)的文件描述符。
2.區別
1)數據類型不一致:
stdin類型為 FILE*
STDIN_FILENO類型為 int
使用stdin的函數主要有:fread、fwrite、fclose等,基本上都以f開頭
使用STDIN_FILENO的函數有:read、write、close等
2)stdin等是FILE *類型,屬于標準I/O,高級的輸入輸出函數。在<stdio.h>。
STDIN_FILENO等是文件描述符,是非負整數,一般定義為0, 1, 2,屬于沒有buffer的I/O,直接調用系統調用,在<unistd.h>。
3)STDIN_FILENO 是標準輸入的文件描述符
#define STDIN_FILENO 0 /* Standard input. */
#define STDOUT_FILENO 1 /* Standard output. */
#define STDERR_FILENO 2 /* Standard error output. */
4)層次不一樣。STDIN 屬于標準庫處理的輸入流,其聲明為 FILE 型的,對應的函數前面都有f開頭,如fopen/fread/fwrite/fclose 標準庫調用等
STDIN_FILENO屬于系統API接口庫,其聲明為 int 型,是一個打開文件句柄,對應的函數主要包括 open/read/write/close 等系統級調用。
標準庫內封裝了系統 API 調用,如 fread 內部實現調用 read。
5)操作系統一級提供的文件API都是以文件描述符來表示文件。STDIN_FILENO就是標準輸入設備(一般是鍵盤)的文件描述符。
6)曾經很納悶,為什么一個整形fd(STDIN_FILENO=0)就可以代表一個打開的文件呢?
后來明白了,和我們的手機號是類似的,手機號只是一個9位數的整形,但是在移動通話網絡里,它就可以用來區分不同的手機終端。
標準C++一級提供的文件操作函數庫都是用FILE*來表示文件,stdin就是指向標準輸入設備文件的FILE*。?
總結
以上是生活随笔為你收集整理的sigaction 函数,sigemptyset()函数,fcntl()函数,isatty()函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux线程-互斥锁pthread_
- 下一篇: Linux编程下open()函数的用法