IPC--信号操作-example

本文详细介绍了Linux环境下信号的应用,包括安装信号、处理信号和发送信号的基本操作。通过两个实例演示了如何实现信号发送与接收,以及如何利用信号传递附加信息。重点阐述了信号处理函数的使用和信号的排队问题。

linux下的信号应用,简单的讲只有三件事情:

  1. 安装信号(推荐使用sigaction());
  2. 实现三参数信号处理函数,void handler(int signal,struct siginfo *info, void *);
  3. 发送信号,推荐使用sigqueue()。

demo1:信号发送及处理

#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
void new_op(int,siginfo_t*,void*);
int main(int argc,char**argv)
{
        struct sigaction act;  
        int sig;
        sig=atoi(argv[1]);
        
        sigemptyset(&act.sa_mask);
        act.sa_flags=SA_SIGINFO;
        act.sa_sigaction=new_op;
        
        if(sigaction(sig,&act,NULL) < 0)
        {
               printf("install sigal error\n");
        }
        
        while(1)
        {
               sleep(2);
               printf("wait for the signal\n");
        }
}
void new_op(int signum,siginfo_t *info,void *myact)
{
        printf("receive signal %d", signum);
        sleep(5);
}

 

说明,命令行参数为信号值,后台运行sigreceive signo &,可获得该进程的ID,假设为pid,然后再另一终端上运行kill -s signo pid验证信号的发送接收及处理。同时,可验证信号的排队问题。 


实例二:信号传递附加信息

功能:向进程本身发送信号,并传递指针参数;

#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
void new_op(int,siginfo_t*,void*);
int main(int argc,char**argv)
{
        struct sigaction act;  
        union sigval mysigval;
        int i;
        int sig;
        pid_t pid;             
        char data[10];
        memset(data,0,sizeof(data));
        for(i=0;i < 5;i++)
               data[i]='2';
        mysigval.sival_ptr=data;
        
        sig=atoi(argv[1]);
        pid=getpid();
        
        sigemptyset(&act.sa_mask);
        act.sa_sigaction=new_op;//三参数信号处理函数
        act.sa_flags=SA_SIGINFO;//信息传递开关
        if(sigaction(sig,&act,NULL) < 0)
        {
               printf("install sigal error\n");
        }
        while(1)
        {
               sleep(2);
               printf("wait for the signal\n");
               sigqueue(pid,sig,mysigval);//向本进程发送信号,并传递附加信息
        }
}
void new_op(int signum,siginfo_t *info,void *myact)//三参数信号处理函数的实现
{
        int i;
        for(i=0;i<10;i++)
        {
               printf("%c\n ",(*( (char*)((*info).si_ptr)+i)));
        }
        printf("handle signal %d over;",signum);
}

 

这个例子中,信号实现了附加信息的传递,信号究竟如何对这些信息进行处理则取决于具体的应用。



### 动态信号量与中断的交互 在 RT-Thread Studio 中,动态信号量可以通过 `rt_sem_create` 函数创建,并通过特定函数实现线程间以及线程与中断之间的通信。以下是关于如何使用动态信号量与中断进行交互的具体说明。 #### 创建动态信号量 动态信号量可以在线程运行期间按需分配内存并创建。其基本语法如下: ```c rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag); ``` 其中: - `name`: 信号量名称。 - `value`: 初始化计数值。 - `flag`: 设置信号量类型(如优先级继承等)。通常设置为 `RT_IPC_FLAG_FIFO` 或其他标志位[^1]。 例如,创建一个初始值为 0 的信号量: ```c rt_sem_t sem = rt_sem_create("example_sem", 0, RT_IPC_FLAG_FIFO); if (sem == RT_NULL) { LOG_E("Failed to create semaphore"); } ``` #### 在中断中释放信号量 为了使中断能够向线程发送信号,在中断服务程序中应调用 `rt_sem_release` 来释放信号量。需要注意的是,由于中断上下文中无法挂起操作,因此不能直接调用可能阻塞的操作函数。以下是一个典型的例子: ```c void interrupt_handler(void) { /* 假设已经定义了一个全局信号量变量 */ extern rt_sem_t example_sem; /* 向信号量添加资源实例 */ if (rt_sem_release(example_sem) != RT_EOK) { LOG_W("Semaphore release failed in ISR"); } } ``` #### 线程等待信号量 线程可以在指定的时间范围内或者无限期地等待信号量被触发。这通常由 `rt_sem_take` 实现: ```c /* 阻塞直到获取到信号量 */ if (rt_sem_take(sem, RT_WAITING_FOREVER) == RT_EOK) { LOG_I("Semaphore acquired successfully!"); } else { LOG_E("Failed to take semaphore"); } ``` 如果希望设定超时时间,则可替换参数中的 `RT_WAITING_FOREVER` 为具体的毫秒数。 #### 综合示例代码 下面提供了一段完整的代码片段展示如何利用动态信号量来协调线程和中断的行为: ```c #include <rtthread.h> #include <board.h> static rt_sem_t example_sem = RT_NULL; void thread_entry(void* parameter) { while (1) { /* 尝试获取信号量 */ if (rt_sem_take(example_sem, RT_WAITING_FOREVER) == RT_EOK) { LOG_I("Interrupt triggered and signal received."); /* 执行某些任务逻辑 */ rt_thread_mdelay(500); // 模拟延迟处理 LOG_I("Task completed after receiving the signal."); } else { LOG_E("Error occurred when taking semaphore."); } } } void interrupt_handler(void) { /* 如果尚未初始化则跳过 */ if (!example_sem) return; /* 发布信号给线程 */ if (rt_sem_release(example_sem) != RT_EOK) { LOG_W("Failed releasing semaphore from ISR."); } /* 清理硬件状态或其他必要动作 */ } int main(void) { /* 创建信号量对象 */ example_sem = rt_sem_create("example_semaphore", 0, RT_IPC_FLAG_FIFO); if (!example_sem) { LOG_E("Failed creating semaphore object."); return -1; } /* 开启新线程监听信号 */ rt_thread_t tid = rt_thread_create( "listener", thread_entry, RT_NULL, 1024, RT_THREAD_PRIORITY_MAX / 2, 20 ); if (tid && rt_thread_startup(tid)) { LOG_E("Failed starting listener thread."); } /* 主循环保持活动 */ while (1) { rt_thread_mdelay(1000); } return RT_EOK; } ``` 此代码展示了如何在一个简单的场景下配置信号量机制以支持线程与中断协作[^2]。 ---
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值