几个信号处理函数和一些信号相关的结构体

这些定义主要都在signal.h中:

1. 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


2. int sigaddset(sigset_t *set,int signum);

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

返回值:

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

/* We don't use <linux/bitops.h> for these because there is no need to
   be atomic.  */
static inline void sigaddset(sigset_t *set, int _sig)
{
        unsigned long sig = _sig - 1;
        if (_NSIG_WORDS == 1)
                set->sig[0] |= 1UL << sig;
        else
                set->sig[sig / _NSIG_BPW] |= 1UL << (sig % _NSIG_BPW);
}

The sigaddset() function adds the individual signal specified by the signo to the signal set pointed to by set. Applications must call either sigemptyset() or sigfillset() at least once for each object of type sigset_t prior to any other use of that object. If such an object is not initialised in this way, but is nonetheless supplied as an argument to any of sigaction(), sigaddset(), sigdelset(),sigismember(), sigpending() or sigprocmask(), the results are undefined.

3.sigdelset(从信号集里删除一个信号)
相关函数 sigemptyset,sigfillset,sigaddset,sigismember

表头文件 #include<signal.h>

定义函数 int sigdelset(sigset_t * set,int signum);

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

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

错误代码 EFAULT 参数set指针地址无法存取
EINVAL 参数signum非合法的信号编号

4. 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指针地址无法存取

5. 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 非合法的信号编号

6. sigpending(查询被搁置的信号)
相关函数 signal,sigaction,sigprocmask,sigsuspend

表头文件 #include<signal.h>

定义函数 int sigpending(sigset_t *set);

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

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

错误代码 EFAULT 参数set指针地址无法存取
EINTR 此调用被中断。

7.  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 此调用被中断


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,需要定义一个结构体来表示读写锁的控制结构,如下所示: ```c typedef struct rwlock { rt_uint16_t read_count; // 读者数量 rt_uint16_t write_count; // 写者数量 rt_sem_t read_sem; // 读信号量 rt_sem_t write_sem; // 写信号量 } rwlock_t; ``` 其中,`read_count` 表示当前有多少个读者正在读取数据,`write_count` 表示当前有多少个写者正在修改数据,`read_sem` 是用来控制读者的信号量,`write_sem` 是用来控制写者的信号量。 接下来,定义相关的 API 函数: ```c void rwlock_init(rwlock_t *lock); void rwlock_read_lock(rwlock_t *lock); void rwlock_read_unlock(rwlock_t *lock); void rwlock_write_lock(rwlock_t *lock); void rwlock_write_unlock(rwlock_t *lock); ``` 其中,`rwlock_init` 用于初始化读写锁,`rwlock_read_lock` 和 `rwlock_write_lock` 分别用于获取读锁和写锁,`rwlock_read_unlock` 和 `rwlock_write_unlock` 分别用于释放读锁和写锁。 下面是具体实现: ```c void rwlock_init(rwlock_t *lock) { lock->read_count = 0; lock->write_count = 0; rt_sem_init(&(lock->read_sem), "read_sem", 0, RT_IPC_FLAG_FIFO); rt_sem_init(&(lock->write_sem), "write_sem", 1, RT_IPC_FLAG_FIFO); } void rwlock_read_lock(rwlock_t *lock) { rt_sem_take(&(lock->write_sem), RT_WAITING_FOREVER); rt_atomic_inc(&(lock->read_count)); if (lock->read_count == 1) { rt_sem_take(&(lock->read_sem), RT_WAITING_FOREVER); } rt_sem_release(&(lock->write_sem)); } void rwlock_read_unlock(rwlock_t *lock) { rt_atomic_dec(&(lock->read_count)); if (lock->read_count == 0) { rt_sem_release(&(lock->read_sem)); } } void rwlock_write_lock(rwlock_t *lock) { rt_sem_take(&(lock->write_sem), RT_WAITING_FOREVER); rt_atomic_inc(&(lock->write_count)); if (lock->write_count == 1) { rt_sem_take(&(lock->read_sem), RT_WAITING_FOREVER); } rt_sem_release(&(lock->write_sem)); } void rwlock_write_unlock(rwlock_t *lock) { rt_atomic_dec(&(lock->write_count)); if (lock->write_count == 0) { rt_sem_release(&(lock->read_sem)); } } ``` 在实现读锁和写锁的时候,需要注意以下几点: 1. 获取读锁时,需要先获取写锁,然后再增加读者数量,如果是第一个读者,需要获取读信号量。 2. 释放读锁时,需要减少读者数量,如果没有读者,需要释放读信号量。 3. 获取写锁时,需要先获取写锁,然后再增加写者数量,如果是第一个写者,需要获取读信号量。 4. 释放写锁时,需要减少写者数量,如果没有写者,需要释放读信号量。 这样就实现了一个基于 rt thread 的读写锁。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值