sleep()和sched_yield()
sched_yield()会让出当前线程的CPU占有权,然后把线程放到静态优先队列的尾端,然后一个新的线程会占用CPU。那这个和sleep()有啥区别呢?
sched_yield()这个函数可以使用另一个级别等于或高于当前线程的线程先运行。如果没有符合条件的线程,那么这个函数将会立刻返回然后继续执行当前线程的程序。
而sleep则是等待一定时间后等待CPU的调度,然后去获得CPU资源(这也是usleep()为什么不准的原因)。
那么什么时候使用sched_yield()呢?
有策略的调用sched_yield()能在资源竞争情况很严重时,通过给其他的线程或进程运行机会的方式来提升程序的性能。也就是说,调用sched_yield()能让你的当前线程让出资源,通过一定的策略调用sched_yield()满足你的业务要求可以保证各个线程或进程都有机会运行。
nice函数
功能描述
改变进程优先级,也就是改变进程执行的优先顺序。
函数定义
int nice(int inc);
返回值
成功执行时,返回新的nice值。失败返回-1
参数介绍
inc数值越大则优先级越低(进程执行慢),超级用户可以使用负的inc 值,使优先顺序靠前,进程执行较快。nice的取值范围可参考getpriority的描述。
sleep、usleep、nanosleep、poll和select
函数 | 性质 | 精准度 | 线程安全 | 信号安全 | xxxx |
---|---|---|---|---|---|
sleep | libc库函数 | 秒 | 是 | 不能和alarm同时使用 | 有些是基于alarm实现的,所以不能和alarm同时使用 |
usleep | libc库函数 | 微秒 | - | - | POSIX.1-2001已将usleep标注为废弃,POSIX.1-2008已删除usleep,应当使用nanosleep替代usleep |
nanosleep | 系统调用 | 纳秒 | 是 | 不确定 | 即使被信号中断,也可实现实际睡眠时长不小于参数指定时长 |
clock_nanosleep | 系统调用 | 纳秒 | 是 | 不确定 | 区别于nanosleep,可选择为相对或绝对时间,其次是可以选择使用哪个时钟 |
poll | 系统调用 | 毫秒 | 是 | 是 | 在协程库libco中可安全使用,如被信号中断,则实际睡眠时长会小于参数指定的时长 |
ppoll | 系统调用 | 纳秒 | 是 | 是 | 如被信号中断,则实际睡眠时长会小于参数指定的时长 |
select | 系统调用 | 微秒 | 是 | 是 | 即使被信号中断,也可实现实际睡眠时长不小于参数指定时长 |
pselect | 系统调用 | 纳秒 | 是 | 是 | 如被信号中断,则实际睡眠时长会小于参数指定的时长 |
简单实例:
/* 基于 nanosleep 的 毫秒级封装 */
void m_sleep(unsigned int milliseconds)
{
struct timespec ts = {
.tv_sec = milliseconds / 1000,
.tv_nsec = (milliseconds % 1000) * 1000000
};
while((-1 == nanosleep(&ts, &ts)) && EINTR == errno);
}
/* 基于 nanosleep 的 微妙级封装 */
void u_sleep(unsigned int microseconds)
{
struct timespec ts = {
.tv_sec = microseconds / 1000000,
.tv_nsec = (microseconds % 1000000) * 1000
};
while ((-1 == nanosleep(&ts, &ts)) && EINTR == errno);
}
void u_sleep2(unsigned int microseconds)
{
struct timeval tv = {
.tv_sec = microseconds / 1000000,
.tv_usec = microseconds % 1000000
};
select(0, NULL, NULL, NULL, &tv);
}