欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C中信号处理函数

程序员文章站 2022-03-31 10:37:03
整体概况 alarm():设置信号传送闹钟 kill():传送信号给指定的进程 pause():让进程暂停直到信号出现 sigaddset():增加一个信号至信号集...

整体概况

alarm():设置信号传送闹钟
kill():传送信号给指定的进程
pause():让进程暂停直到信号出现
sigaddset():增加一个信号至信号集
sigdelset():从信号集里删除一个信号
sigemptyset():初始化信号集
sigfillset():将所有信号加入至信号集
sigismember():测试某个信号是否已经加入至信号
signal():设置信号处理方式
sigpending():查询被搁置的信号
sigprocmask():查询或设置信号遮罩
sleep():让进程暂停执行一段时间
ferror():查询文件流是否有错误发生
strerror():返回错误原因的描述字符串
mkfifo():建立具名管道
pclose():关闭管道I/O
popen():建立管道I/O
sigaction():查询或设置信号处理方式

详细介绍

alarm函数

unsigned int alarm(unsigned int seconds);

函数说明:alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的线程。如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。

返回值:返回之前闹钟的秒数,如果之前未设闹钟,则返回0。

kill函数

int kill(pid_t pid, int sig);

函数说明:kill()可以用来送参数sig指定的信号给参数pid指定的进程。参数pid有几种情况:

1):pid>0 将信号传给进程识别码为pid的进程
2):pid=0 将信号传给和目前进程相同进程组的所有进程
3):pid=-1 将信号广播传送给系统内所有的进程
4):pid<0 将信号传给进程组标识码为pid绝对值的所有进程参数sig代表的信号编号

返回值:执行成功则返回0,如果有错误则返回-1。

错误代码:

1):EINVAL 参数sig不合法
2):ESRCH 参数pid所指定的进程或进程组不存在
3):EPERM 权限不够无法传送信号给指定进程

sigaction函数

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);
};
1):sa_handler 此参数和signal()的参数handler相同,代表新的信号处理函数;
2):sa_mask 用来设置在处理该信号时暂时将sa_mask指定的信号搁置;
3):sa_restorer 此参数没有使用
4):sa_flags 用来设置信号处理的其他相关操作,下列的数值可用:
    A_NOCLDSTOP:如果参数signum为SIGCHLD,则当子进程暂停时不会通知父进程
    SA_ONESHOT/SA_RESETHAND:当调用新的信号处理函数前,将此信号处理方式改为系统预设的方式
    SA_RESTART:被信号中断的系统调用会自行重启
    SA_NOMASK/SA_NODEFER:在处理此信号未结束前不理会此信号的再次到来。如果参数oldact不是NULL指针,则原来的信号处理方式会由此结构sigaction返回。

返回值:执行成功则返回0,如果有错误则返回-1。

错误代码:

1):EINVAL 参数signum不合法,或是企图拦截SIGKILL/SIGSTOP信号
2):EFAULT 参数act,oldact指针地址无法存取
3):EINTR 此调用被中断

pause函数

int pause(void);

函数说明:pause()会令目前的进程暂停(进入睡眠状态),直到被信号(signal)所中断。

返回值:只返回-1。

错误代码:

EINIT有信号到达中断了此函数。

sigaddset函数

int sigaddset(sigset_t *set, int signum);

函数说明:sigaddset()用来将参数signum代表的信号加入至参数set信号集里。

返回值:执行成功则返回0,如果有错误则返回-1。

错误代码:

1):EFAULT 参数set指针地址无法存取
2):EINVAL 参数signum非合法的信号编号

sigdelset函数

int sigdelset(sigset_t *set, int signum);

函数说明:sigdelset()用来将参数signum代表的信号从参数set信号集里删除。

返回值:执行成功则返回0,如果有错误则返回-1。

错误代码:

1):EFAULT 参数set指针地址无法存取
2):EINVAL 参数signum非合法的信号编号

sigemptyset函数

int sigemptyset(sigset_t *set);

函数说明:sigemptyset()用来将参数set信号集初始化并清空。

返回值:执行成功则返回0,如果有错误则返回-1。

错误代码:

EFAULT 参数set指针地址无法存取

sigfillset函数

int sigfillset(sigset_t *set);

函数说明:sigfillset()用来将参数set信号集初始化,然后把所有的信号加入到此信号集里。

返回值:执行成功则返回0,如果有错误则返回-1。

错误代码:

EFAULT 参数set指针地址无法存取

sigismember函数

int sigisnumber(const sigset_t *set, int signum);

函数说明:sigisnumber()用来测试参数signum代表的信号是否已加入至参数set信号集里。如果信号集里已有该信号,则返回1,否则返回0。

返回值:信号集已有该信号则返回1,没有则返回0。如果有错误则返回-1。

错误代码

1):EFAULT 参数set指针地址无法存取
2):EINVAL 参数signum非合法的信号编号

signal函数

void(signal(int signum, void( handler)(int)))(int);

函数说明:signal()会依参数signum指定的信号编号来设置该信号的处理函数。当指定的信号到达时就会跳转到参数handler指定的函数执行。如果参数handler不是函数指针,则必须是下列两个常数之一:

1):SIG_IGN 忽略参数signum指定的信号
2):SIG_DFL 将参数signum指定的信号量重设为核心预设的信号处理方式

返回值:返回先前的信号处理函数指针,如果有错误则返回SIG_ERR(-1)

注意:此信号在发生跳转到自动的handler处理函数执行后,系统会自动将此处理函数换回原来系统预设的处理方式,如果要改变此操作可修改sigaction()函数。

sigpending函数

函数说明:sigpending()会将被搁置的信号集合由参数set指针返回。

返回值:执行成功则返回0,如果有错误则返回-1。

错误代码:

EFAULT 参数set指针地址无法存取
EINTR 此调用被中断

sigprocmask函数

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

函数说明:sigprocmask()可以用来改变目前的信号遮罩,其操作依参数how来决定:

1):SIG_BLOCK 新的信号遮罩由目前的信号遮罩和参数set指定的信号遮罩做联集
2):SIG_UNBLOCK 将目前的信号遮罩删除掉参数set指定的信号遮罩
3):SIG_SETMASK 将目前的信号遮罩设成参数set指定的信号遮罩。如果参数oldset不是NULL指针,那么目前的信号遮罩会由此指针返回。

返回值:执行成功则返回0,如果有错误则返回-1。

错误代码:

1):EFAULT 参数set,oldset指针地址无法存取
2):EINIT 此调用被中断

sleep函数

unsigned int sleep(unsigned int seconds);

函数说明:sleep()会令目前的进程暂停,直到达到参数seconds所指定的时间,或是被信号所中断。

返回值:若进程暂停到参数seconds所指定的时间则返回0,若有信号中断则返回剩余秒数。

ferror函数

int ferror(FILE *stream);

函数说明:ferror()用来检查参数stream所指定的文件流是否发生了错误情况,如有错误发生则返回非0值。

返回值:如果文件流有错误发生则返回非0值。

perror函数

void perror(char *string);

函数说明:perror()用来将上一个函数发生错误的原因输出到标准错误(stderr)。参数string所指的字符串会先打印出,后面再加上错误原因字符串,此错误原因依照全局变量errno的值来决定要输出的字符串。

在库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。当你调用”某些”函数出错时,该函数已经重新设置了errno的值。perror函数只是将你输入的一些信息和现在的errno所对应的错误一起输出。

strerror函数

char *strerror(int errnum);

函数说明:strerror()用来依参数errnum的错误代码来查询其错误原因的描述字符串,然后将该字符串指针返回。

返回值:返回描述错误原因的字符串指针。

mkfifo函数

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中。

错误代码:
1):EACCESS 参数pathname 所指定的目录路径无可执行的权限
2):EEXIST 参数pathname 所指定的文件已存在
3):ENAMETOOLONG 参数pathname 的路径名称太长
4):ENOENT 参数pathname 包含的目录不存在
5):ENOSPC 文件系统的剩余空间不足
6):ENOTDIR 参数pathname 路径中的目录存在但却非真正的目录
7):EROFS 参数pathname 指定的文件存在于只读文件系统内

pclose函数

int pclose(FILE *stream);

函数说明:pclose()用来关闭有popen所建立的管道及文件指针。参数stream为先前有popen()返回的文件指针。

返回值:返回子进程的结束状态。如果有错误则返回-1,错误原因存于errno中。

错误代码:ECHILD pclose()无法取得子进程的结束状态。

popen函数

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()会继承环境变量,通过环境变量可能会造成系统安全的问题。