alarm(設定訊號傳送鬧鐘)
相關函數 signal,sleep
表標頭檔 #include<unistd.h>
定義函數 unsigned int alarm(unsigned int seconds);
函數說明 alarm()用來設定訊號SIGALRM在經過參數seconds指定的秒數後傳送給目前的進程。如果參數seconds 為0,則之前設定的鬧鐘會被取消,並將剩下的時間返回。
傳回值 返回之前鬧鐘的剩餘秒數,如果之前未設鬧鐘則返回0。
範例 #include<unistd.h>
#include<signal.h>
void handler() {
printf(“hello\n”);
}
main()
{
int i;
signal(SIGALRM,handler);
alarm(5);
for(i=1;i<7;i++){
printf(“sleep %d ...\n”,i);
sleep(1);
}
}
執行 sleep 1 ...
sleep 2 ...
sleep 3 ...
sleep 4 ...
sleep 5 ...
hello
sleep 6 ...
kill(傳送訊號給指定的進程)
相關函數 raise,signal
表標頭檔 #include<sys/types.h>
#include<signal.h>
定義函數 int kill(pid_t pid,int sig);
函數說明 kill()可以用來送參數sig指定的訊號給參數pid指定的進程。參數pid有幾種情況:
pid>0 將訊號傳給進程識別碼為pid 的進程。
pid=0 將訊號傳給和目前進程相同進程組的所有進程
pid=-1 將訊號廣播傳送給系統內所有的進程
pid<0 將訊號傳給進程組識別碼為pid絕對值的所有進程
參數sig代表的訊號編號可參考附錄D
傳回值 執行成功則返回0,如果有錯誤則返回-1。
錯誤碼 EINVAL 參數sig 不合法
ESRCH 參數pid 所指定的進程或進程組不存在
EPERM 許可權不夠無法傳送訊號給指定進程
範例 #include<unistd.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/wait.h>
main()
{
pid_t pid;
int status;
if(!(pid= fork())){
printf(“Hi I am child process!\n”);
sleep(10);
return;
}
else{
printf(“send signal to child process (%d) \n”,pid);
sleep(1);
kill(pid ,SIGABRT);
wait(&status);
if(WIFSIGNALED(status))
printf(“chile process receive signal %d\n”,WTERMSIG(status));
}
}
執行 sen signal to child process(3170)
Hi I am child process!
child process receive signal 6
pause(讓進程暫停直到訊號出現)
相關函數 kill,signal,sleep
表標頭檔 #include<unistd.h>
定義函數 int pause(void);
函數說明 pause()會令目前的進程暫停(進入睡眠狀態),直到被訊號(signal)所中斷。
傳回值 只返回-1。
錯誤碼 EINTR 有訊號到達中斷了此函數。
sigaction(查詢或設定訊號處理方式)
相關函數 signal,sigprocmask,sigpending,sigsuspend
表標頭檔 #include<signal.h>
定義函數 int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);
函數說明 sigaction()會依參數signum指定的訊號編號來設定該訊號的處理函數。參數signum可以指定SIGKILL和SIGSTOP以外的所有訊號。
如參數結構sigaction定義如下
struct sigaction
{
void (*sa_handler) (int);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer) (void);
}
sa_handler此參數和signal()的參數handler相同,代表新的訊號處理函數,其他意義請參考signal()。
sa_mask 用來設定在處理該訊號時暫時將sa_mask 指定的訊號擱置。
sa_restorer 此參數沒有使用。
sa_flags 用來設定訊號處理的其他相關操作,下列的數值可用。
OR 運算(|)組合
A_NOCLDSTOP : 如果參數signum為SIGCHLD,則當子進程暫停時並不會通知父進程
SA_ONESHOT/SA_RESETHAND:當調用新的訊號處理函數前,將此訊號處理方式改為系統預設的方式。
SA_RESTART:被訊號中斷的系統調用會自行重啟
SA_NOMASK/SA_NODEFER:在處理此訊號未結束前不理會此訊號的再次到來。
如果參數oldact不是NULL指標,則原來的訊號處理方式會由此結構sigaction 返回。
傳回值 執行成功則返回0,如果有錯誤則返回-1。
錯誤碼 EINVAL 參數signum 不合法, 或是企圖攔截SIGKILL/SIGSTOPSIGKILL訊號
EFAULT 參數act,oldact指標地址無法存取。
EINTR 此調用被中斷
範例 #include<unistd.h>
#include<signal.h>
void show_handler(struct sigaction * act)
{
switch (act->sa_flags)
{
case SIG_DFL:printf(“Default action\n”);break;
case SIG_IGN:printf(“Ignore the signal\n”);break;
default: printf(“0x%x\n”,act->sa_handler);
}
}
main()
{
int i;
struct sigaction act,oldact;
act.sa_handler = show_handler;
act.sa_flags = SA_ONESHOT|SA_NOMASK;
sigaction(SIGUSR1,&act,&oldact);
for(i=5;i<15;i++)
{
printf(“sa_handler of signal %2d =”.i);
sigaction(i,NULL,&oldact);
}
}
執行 sa_handler of signal 5 = Default action
sa_handler of signal 6= Default action
sa_handler of signal 7 = Default action
sa_handler of signal 8 = Default action
sa_handler of signal 9 = Default action
sa_handler of signal 10 = 0x8048400
sa_handler of signal 11 = Default action
sa_handler of signal 12 = Default action
sa_handler of signal 13 = Default action
sa_handler of signal 14 = Default action
sigaddset(增加一個訊號至訊號集)
相關函數 sigemptyset,sigfillset,sigdelset,sigismember
表標頭檔 #include<signal.h>
定義函數 int sigaddset(sigset_t *set,int signum);
函數說明 sigaddset()用來將參數signum 代表的訊號加入至參數set 訊號集裡。
傳回值 執行成功則返回0,如果有錯誤則返回-1。
錯誤碼 EFAULT 參數set指標地址無法存取
EINVAL 參數signum非合法的訊號編號
sigdelset(從訊號集裡刪除一個訊號)
相關函數 sigemptyset,sigfillset,sigaddset,sigismember
表標頭檔 #include<signal.h>
定義函數 int sigdelset(sigset_t * set,int signum);
函數說明 sigdelset()用來將參數signum代表的訊號從參數set訊號集裡刪除。
傳回值 執行成功則返回0,如果有錯誤則返回-1。
錯誤碼 EFAULT 參數set指標地址無法存取
EINVAL 參數signum非合法的訊號編號
sigemptyset(初始化訊號集)
相關函數 sigaddset,sigfillset,sigdelset,sigismember
表標頭檔 #include<signal.h>
定義函數 int sigemptyset(sigset_t *set);
函數說明 sigemptyset()用來將參數set訊號集初始化並清空。
傳回值 執行成功則返回0,如果有錯誤則返回-1。
錯誤碼 EFAULT 參數set指標地址無法存取
sigfillset(將所有訊號加入至訊號集)
相關函數 sigempty,sigaddset,sigdelset,sigismember
表標頭檔 #include<signal.h>
定義函數 int sigfillset(sigset_t * set);
函數說明 sigfillset()用來將參數set訊號集初始化,然後把所有的訊號加入到此訊號集裡。
傳回值 執行成功則返回0,如果有錯誤則返回-1。
附加說明 EFAULT 參數set指標地址無法存取
sigismember(測試某個訊號是否已加入至訊號集裡)
相關函數 sigemptyset,sigfillset,sigaddset,sigdelset
表標頭檔 #include<signal.h>
定義函數 int sigismember(const sigset_t *set,int signum);
函數說明 sigismember()用來測試參數signum 代表的訊號是否已加入至參數set訊號集裡。如果訊號集裡已有該訊號則返回1,否則返回0。
傳回值 訊號集已有該訊號則返回1,沒有則返回0。如果有錯誤則返回-1。
錯誤碼 EFAULT 參數set指標地址無法存取
EINVAL 參數signum 非合法的訊號編號
signal(設定訊號處理方式)
相關函數 sigaction,kill,raise
表標頭檔 #include<signal.h>
定義函數 void (*signal(int signum,void(* handler)(int)))(int);
函數說明 signal()會依參數signum 指定的訊號編號來設定該訊號的處理函數。當指定的訊號到達時就會跳轉到參數handler指定的函數執行。如果參數handler不是函數指標,則必須是下列兩個常數之一:
SIG_IGN 忽略參數signum指定的訊號。
SIG_DFL 將參數signum 指定的訊號重設為核心預設的訊號處理方式。
關於訊號的編號和說明,請參考附錄D
傳回值 返回先前的訊號處理函數指標,如果有錯誤則返回SIG_ERR(-1)。
附加說明 在訊號發生跳轉到自定的handler處理函數執行後,系統會自動將此處理函數換回原來系統預設的處理方式,如果要改變此操作請改用sigaction()。
範例 參考alarm()或raise()。
sigpending(查詢被擱置的訊號)
相關函數 signal,sigaction,sigprocmask,sigsuspend
表標頭檔 #include<signal.h>
定義函數 int sigpending(sigset_t *set);
函數說明 sigpending()會將被擱置的訊號集合由參數set指標返回。
傳回值執 行成功則返回0,如果有錯誤則返回-1。
錯誤碼 EFAULT 參數set指標地址無法存取
EINTR 此調用被中斷。
sigprocmask(查詢或設定訊號遮罩)
相關函數 signal,sigaction,sigpending,sigsuspend
表標頭檔 #include<signal.h>
定義函數 int sigprocmask(int how,const sigset_t *set,sigset_t * oldset);
函數說明 sigprocmask()可以用來改變目前的訊號遮罩,其操作依參數how來決定
SIG_BLOCK 新的訊號遮罩由目前的訊號遮罩和參數set 指定的訊號遮罩作聯集
SIG_UNBLOCK 將目前的訊號遮罩刪除掉參數set指定的訊號遮罩
SIG_SETMASK 將目前的訊號遮罩設成參數set指定的訊號遮罩。
如果參數oldset不是NULL指標,那麼目前的訊號遮罩會由此指標返回。
傳回值 執行成功則返回0,如果有錯誤則返回-1。
錯誤碼 EFAULT 參數set,oldset指標地址無法存取。
EINTR 此調用被中斷
sleep(讓進程暫停執行一段時間)
相關函數 signal,alarm
表標頭檔 #include<unistd.h>
定義函數 unsigned int sleep(unsigned int seconds);
函數說明 sleep()會令目前的進程暫停,直到達到參數seconds 所指定的時間,或是被訊號所中斷。
傳回值 若進程暫停到參數seconds 所指定的時間則返回0,若有訊號中斷則返回剩餘秒數。
ferror(檢查檔案流是否有錯誤發生)
相關函數 clearerr,perror
表標頭檔 #include<stdio.h>
定義函數 int ferror(FILE *stream);
函數說明 ferror()用來檢查參數stream所指定的檔案流是否發生了錯誤情況,如有錯誤發生則返回非0值。
傳回值 如果檔案流有錯誤發生則返回非0值。
perror(列印出錯誤原因資訊字串)
相關函數 strerror
表標頭檔 #include<stdio.h>
定義函數 void perror(const char *s);
函數說明 perror()用來將上一個函數發生錯誤的原因輸出到標準錯誤(stderr)。參數s所指的字串會先列印出,後面再加上錯誤原因字串。此錯誤原因依照全域變數errno的值來決定要輸出的字串。
傳回值
範例 #include<stdio.h>
main()
{
FILE *fp;
fp = fopen(“/tmp/noexist”,”r+”);
if(fp = =NULL) perror(“fopen”);
}
執行 $ ./perror
fopen : No such file or diretory
strerror(返回錯誤原因的描述字串)
相關函數 perror
表標頭檔 #include<string.h>
定義函數 char * strerror(int errnum);
函數說明 strerror()用來依參數errnum的錯誤碼來查詢其錯誤原因的描述字串,然後將該字串指標返回。
傳回值 返回描述錯誤原因的字串指標。
範例 /* 顯示錯誤碼0 至9 的錯誤原因描述*/
#include<string.h>
main()
{
int i;
for(i=0;i<10;i++)
printf(“%d : %s\n”,i,strerror(i));
}
執行 0 : Success
1 : Operation not permitted
2 : No such file or directory
3 : No such process
4 : Interrupted system call
5 : Input/output error
6 : Device not configured
7 : Argument list too long
8 : Exec format error
9 : Bad file descriptor
mkfifo(建立具名管道)
相關函數 pipe,popen,open,umask
表標頭檔 #include<sys/types.h>
#include<sys/stat.h>
定義函數 int mkfifo(const char * pathname,mode_t mode);
函數說明 mkfifo()會依參數pathname建立特殊的FIFO檔案,該檔案必須不存在,而參數mode為該檔案的許可權(mode%~umask),因此umask值也會影響到FIFO檔案的許可權。Mkfifo()建立的FIFO檔案其他進程都可以用讀寫一般檔案的方式存取。當使用open()來開啟FIFO檔案時,O_NONBLOCK旗標會有影響
1、當使用O_NONBLOCK 旗標時,開啟FIFO 檔案來讀取的操作會立刻返回,但是若還沒有其他進程開啟FIFO 檔案來讀取,則寫入的操作會返回ENXIO 錯誤碼。
2、沒有使用O_NONBLOCK 旗標時,開啟FIFO 來讀取的操作會等到其他進程開啟FIFO檔案來寫入才正常返回。同樣地,開啟FIFO檔案來寫入的操作會等到其他進程開啟FIFO 檔案來讀取後才正常返回。
傳回值 若成功則返回0,否則返回-1,錯誤原因存於errno中。
錯誤碼 EACCESS 參數pathname所指定的目錄路徑無可執行檔許可權
EEXIST 參數pathname所指定的檔案已存在。
ENAMETOOLONG 參數pathname的路徑名稱太長。
ENOENT 參數pathname包含的目錄不存在
ENOSPC 檔案系統的剩餘空間不足
ENOTDIR 參數pathname路徑中的目錄存在但卻非真正的目錄。
EROFS 參數pathname指定的檔案存在於唯讀檔案系統內。
範例 #include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
main()
{
char buffer[80];
int fd;
unlink(FIFO);
mkfifo(FIFO,0666);
if(fork()>0){
char s[ ] = “hello!\n”;
fd = open (FIFO,O_WRONLY);
write(fd,s,sizeof(s));
close(fd);
}
else{
fd= open(FIFO,O_RDONLY);
read(fd,buffer,80);
printf(“%s”,buffer);
close(fd);
}
}
執行 hello!
pclose(關閉管道I/O)
相關函數 popen
表標頭檔 #include<stdio.h>
定義函數 int pclose(FILE * stream);
函數說明 pclose()用來關閉由popen所建立的管道及檔案指標。參數stream為先前由popen()所返回的檔案指標。
傳回值 返回子進程的結束狀態。如果有錯誤則返回-1,錯誤原因存於errno中。
錯誤碼 ECHILD pclose()無法取得子進程的結束狀態。
範例 參考popen()。
pipe(建立管道)
相關函數 mkfifo,popen,read,write,fork
表標頭檔 #include<unistd.h>
定義函數 int pipe(int filedes[2]);
函數說明 pipe()會建立管道,並將檔案描述詞由參數filedes數組返回。filedes[0]為管道裡的讀取端,filedes[1]則為管道的寫入端。
傳回值 若成功則返回零,否則返回-1,錯誤原因存於errno中。
錯誤碼 EMFILE 進程已用完檔案描述詞最大量。
ENFILE 系統已無檔案描述詞可用。
EFAULT 參數filedes數組地址不合法。
範例 /* 父進程借管道將字串“hello!\n”傳給子進程並顯示*/
#include <unistd.h>
main()
{
int filedes[2];
char buffer[80];
pipe(filedes);
if(fork()>0){
/* 父進程*/
char s[ ] = “hello!\n”;
write(filedes[1],s,sizeof(s));
}
else{
/*子進程*/
read(filedes[0],buffer,80);
printf(“%s”,buffer);
}
}
執行 hello!
popen(建立管道I/O)
相關函數 pipe,mkfifo,pclose,fork,system,fopen
表標頭檔 #include<stdio.h>
定義函數 FILE * popen( const char * command,const char * type);
函數說明 popen()會調用fork()產生子進程,然後從子進程中調用/bin/sh -c來執行參數command的指令。參數type可使用“r”代表讀取,“w”代表寫入。依照此type值,popen()會建立管道連到子進程的標準輸出裝置或標準輸入裝置,然後返回一個檔案指標。隨後進程便可利用此檔案指標來讀取子進程的輸出裝置或是寫入到子進程的標準輸入裝置中。此外,所有使用檔案指標(FILE*)操作的函數也都可以使用,除了fclose()以外。
傳回值 若成功則返迴文件指標,否則返回NULL,錯誤原因存於errno中。
錯誤碼 EINVAL參數type不合法。
注意事項 在編寫具SUID/SGID許可權的程式時請盡量避免使用popen(),popen()會繼承環境變數,通過環境變數可能會造成系統安全的問題。
範例 #include<stdio.h>
main()
{
FILE * fp;
char buffer[80];
fp=popen(“cat /etc/passwd”,”r”);
fgets(buffer,sizeof(buffer),fp);
printf(“%s”,buffer);
pclose(fp);
}
執行 root :x:0 0: root: /root: /bin/bash