Ubuntu16.04应用程序编程中关于精准定时POSIX和SIGNAL的使用详解

参考1:https://blog.csdn.net/lee244868149/article/details/38710149

参考2:https://blog.csdn.net/weixin_34228387/article/details/86405426

需求:

       在写嵌入式软件的时候,需要用到近乎us级别的定时器来实现扫描电压;逻辑是每nus增加nuv,从而实现扫描电压的过程。除了定时器还用到了信号。

 

理论资料 POSIX定时器:

查阅参考2

Struct timespec

{

       _time_t tv_sec;            //赋的值是以s为单位

       _syscall_slong_t tv_nsec;      //赋的值是以ns为单位

}

Struct itimerspec

{

       Struct timespec it_interval;   //从使能定时器开始计时的时间

       Struct timespec it_value;      //如果设定此参数,那么定时器会以设定的参数循环执行

}

timer_create();创建一个新的定时器,放回一个唯一的定时器ID

timer_delete();删除一个已经存在的定时器,删除前先让定时器停止;下面会谈到如何让定时器停止;

timer_settime();设置定时器参数;开始定时器;停止定时器都用的这个函数

timer_gettime();

timer_getoverrun();

实际应用:

int posix_timer_id;

struct itimerspec ts;

ts.it_value.tv_sec = 1;  //  1

ts.it_value.tv_ nsec = 0; //  2

ts.it_ interval.tv_sec = 1;//  3

ts.it_ interval.tv_ nsec = 0;// 4

//第1、2来设置第一次定时的时间;第2、3来设置循环定时的时间

timer_settime(posix_timer_id, 0, &ts, 0);//  5

//第5来设置定时器参数,并且开始定时器

ts.it_value.tv_sec = 0;  //  6

ts.it_value.tv_ nsec = 0; //  7

ts.it_ interval.tv_sec = 0;//  8

ts.it_ interval.tv_ nsec = 0;// 9

timer_settime(posix_timer_id, 0, &ts, 0);

//第 6、7、8、9都设置为0时,表示停止定时器

timer_delete(posix_timer_id);//10

//第10来删除定时器

 

理论资料 SIGNAL信号:

查阅参考1

实际应用:

//创建线程前,将signal_mask信号集从信号掩码中移除

sigemptyset(&signal_mask);

sigaddset(&signal_mask, SIGUSR1);

sigaddset(&signal_mask, SIGTERM);

pthread_sigmask(SIG_UNBLOCK, &signal_mask, NULL);      

                

//创建新线程, 服务器初接收函数                                            

pthread_create(&threadID_Sample, NULL, ThreadFunction, NULL);
//创建线程后,屏蔽signal_mask信号集;

sigemptyset(&signal_mask);

sigaddset(&signal_mask, SIGUSR1);

sigaddset(&signal_mask, SIGTERM);

pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);

 

/************************* ThreadFunction线程函数内*********************************/

//初始化信号参数

act.sa_handler = StartSample_IT;

act.sa_flags = 0;

sigemptyset(&act.sa_mask);

sigaction(SIGUSR1, &act, NULL);
//用来指定定时器到期时要产生的异步通知

memset(&sev, 0, sizeof(sev));

sev.sigev_signo = SIGUSR1;

sev.sigev_notify = SIGEV_SIGNAL;//SIGEV_SIGNAL(产生信号) SIGEV_NONE(不处理) SIGEV_THREAD(新线程处理)SIGEV_THREAD_ID(指定线程处理)
//创建定时器

timer_create(CLOCK_REALTIME, &sev, &posix_timer_id);
//设置定时器并启动

ts.it_value.tv_sec = ns / 1000000000;

ts.it_value.tv_nsec = ns % 1000000000;

printf("ts.it_value.tv_sec:%d\n", ts.it_value.tv_sec);

printf("ts.it_value.tv_nsec:%d\n", ts.it_value.tv_nsec);

timer_settime(posix_timer_id, 0, &ts, 0);
ts.it_value.tv_sec = 0;

ts.it_value.tv_nsec = 0;

timer_settime(posix_timer_id, 0, &ts, 0);//定时器停止

timer_delete(posix_timer_id);//删除定时器                 

pthread_cancel(threadID_Sample);

pthread_join(threadID_Sample, NULL);//回收线程

 

在整个过程中遇到的问题包括:

  1. 信号产生后会传给每个线程,若想只让子线程接收信号,那么就要在父线程中屏蔽该信号。
  2. 在父线程中创建子线程时候,子线程会继承父线程屏蔽的信号,所以在创建线程前要移除被屏蔽的信号。
  3. 不用定时器或者线程了,就要删除和销毁线程
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Ubuntu 16.04上安装Redis有两种方式:apt和编译方式。 第一种方式是使用apt安装Redis。首先,打开终端并更新软件包列表,运行命令“sudo apt update”。然后,安装Redis,运行命令“sudo apt install redis-server”。 在安装完成后,Redis将自动启动,并且将在系统启动时自动运行。可以使用“sudo systemctl status redis-server”命令来检查Redis的运行状态。此外,可以使用“sudo systemctl stop redis-server”和“sudo systemctl start redis-server”命令来停止和启动Redis。 第二种方式是通过编译方式安装Redis。首先,从Redis官方网站下载最新的稳定版本压缩包(例如redis-stable.tar.gz)。然后在终端切换到下载的目录并解压文件,运行命令“tar xzf redis-stable.tar.gz”。 接下来,进入解压后的Redis目录,运行命令“cd redis-stable”。然后,使用“make”命令来编译Redis。编译完成后,运行命令“make test”来进行测试以确保Redis正常工作。 最后,可以使用“sudo make install”命令来安装Redis。安装完成后,可以使用“redis-server”命令启动Redis服务器,并使用“redis-cli”命令连接到Redis并执行各种操作。 无论使用apt还是编译方式安装Redis,都可以通过在终端运行“redis-cli ping”命令来测试Redis是否正常运行。如果返回“PONG”则表示Redis已成功安装和启动。 总之,这两种方式都可以在Ubuntu 16.04上成功安装Redis,选择哪种方式取决于个人偏好和具体需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值