我是靠谱客的博主 开心网络,最近开发中收集的这篇文章主要介绍信号之函数system、sleep、nanosleep以及clock_nanosleep,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

本文来自个人博客:https://dunkwan.cn

文章目录

    • 函数`system`
    • 函数`sleep`、`nanosleep`和`clock_nanosleep`

函数system

由于system执行的命令可能是交互式的命令,因为system的调用者在程序执行时放弃了控制,等待该执行程序的结束,所以system的调用者就不应接收SIGINTSIGQUIT这两个终端产生的信号。

测试示例1:

system实现版本一,为考虑忽略SIGINTSIGQUIT信号。

#include "../../include/apue.h"
#include <sys/wait.h>
#include <unistd.h>

int system(const char *);
static void sig_int(int);
static void sig_chld(int);

int main(void)
{
    if(signal(SIGINT, sig_int) == SIG_ERR)
        err_sys("signal(SIGINT) error");
    if(signal(SIGCHLD, sig_chld) == SIG_ERR)
        err_sys("signal(SIGCHLD) error");
    if(system("/bin/ed") < 0)
        err_sys("system() error");
    return 0;
}

int system(const char *cmdstring)   /* version without signal handling */
{
    pid_t   pid;
    int     status;

    if (cmdstring == NULL)
        return(1);      /* always a command processor with UNIX */

    if ((pid = fork()) < 0) {
        status = -1;    /* probably out of processes */

    } else if (pid == 0) {              /* child */
        execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
        _exit(127);     /* execl error */
    } else {                            /* parent */
        while (waitpid(pid, &status, 0) < 0) {
            if (errno != EINTR) {
                status = -1; /* error other than EINTR from waitpid() */
                break;

            }

        }
    }

    return(status);
}

static void sig_int(int signo)
{
    printf("caught SIGINTn");
}

static void sig_chld(int signo)
{
    printf("caught SIGCHLDn");
}

结果如下:

测试示例2:

system函数版本2,此版本进行了所要求的信号的处理。

#include "../../include/apue.h"
#include <sys/wait.h>

static void sig_int(int);
static void sig_chld(int);
int system(const char *);

int main()
{
    if(signal(SIGINT, sig_int) == SIG_ERR)
        err_sys("signal(SIGINT) error");
    if(signal(SIGCHLD, sig_chld) == SIG_ERR)
        err_sys("signal(SIGCHLD) error");

    if(system("/bin/ed") < 0)
        err_sys("system() error");

    return 0;
}

static void sig_int(int signo)
{
    printf("caught SIGINTn");
}

static void sig_chld(int signo)
{
    printf("caught SIGCHLDn");
}

int system(const char *cmdstring) /* with appropriate signal handling */
{
    pid_t pid;
    int status;
    struct sigaction ignore, saveintr, savequit;
    sigset_t chldmask, savemask;

    if(cmdstring == NULL)
        return (1);

    ignore.sa_handler = SIG_IGN;    /* ignore SIGINT and SIGQUIT */
    sigemptyset(&ignore.sa_mask);
    ignore.sa_flags = 0;
    if(sigaction(SIGINT, &ignore, &saveintr) < 0)
        return (-1);
    if(sigaction(SIGQUIT, &ignore, &savequit) < 0)
        return (-1);
    sigemptyset(&chldmask);
    sigaddset(&chldmask, SIGCHLD);
    if(sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0)
        return (-1);

    if((pid = fork()) < 0){
        status = -1;
    }else if(pid == 0){
        sigaction(SIGINT, &saveintr, NULL);
        sigaction(SIGQUIT, &savequit, NULL);
        sigprocmask(SIG_SETMASK, &savemask, NULL);

        execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
        _exit(127);
    }else{
        while(waitpid(pid, &status, 0) < 0)
            if(errno != EINTR){
                status = -1;
                break;
            }
    }

    if(sigaction(SIGINT, &saveintr, NULL) < 0)
        return (-1);
    if(sigaction(SIGQUIT, &savequit, NULL) < 0)
        return (-1);
    if(sigprocmask(SIG_SETMASK, &savemask, NULL) < 0)
        return (-1);

    return (status);
}

结果如下:

函数sleepnanosleepclock_nanosleep

sleep函数定义如下:

#include <unistd.h>
unsigned int sleep(unsigned int seconds);
返回值:0或未休眠完的秒数。

此函数使调用进程被挂起直到满足下面两个条件之一。

  1. 已经过了seconds所指定的墙上时钟时间。
  2. 调用进程捕捉到一个信号并从信号处理程序返回。

以下是一个POSIX.1的sleep函数的实现。

#include "apue.h"

static void sig_alrm(int signo){
    /* nothing to do, just returned wakes up sigsuspend() */
} 

unsigned int sleep(unsigned int seconds)
{
    struct sigaction newact, oldact;
    sigset_t newmask, oldmask, suspmask;
    unsigned int unslept;
    
    /* set our handler, save previous information */
    newact.sa_handler = sig_alrm;
    sigemptyset(&newact.sa_mask);
    newact.sa_flags = 0;
    sigaction(SIGALRM, &newact, &oldact);
    
    /* block SIGALRM and save current signal mask */
    sigemptyset(&newmask);
    sigaddset(&newmask, SIGALRM);
    sigprocmask(SIG_BLOCK, &newmask, &oldmask);
    
    alarm(seconds);
    suspmask = oldmask;
    
    /* make sure SIGALRM isn't blocked */
    sigdelset(&suspmask, SIGALRM);
    
    /* wait for any signal to be caught  */
    sigsuspend(&suspmask);
    
    /* some signal has been caught, SIGALRM is now blocked */
    unslept = alarm(0);
    
    /* reset previous action */
    sigaction(SIGALRM, &oldact, NULL);
    
    /* reset signal mask, which unblocks SIGALRM */
    sigprocmask(SIG_SETMASK, &oldmask, NULL);
    return (unslept);

nanosleep函数与sleep函数类似,但提供了纳秒级的精度。

#include <time.h>
int nanosleep(const struct timespec *reqtp, struct timespec *remtp);
返回值:若休眠到要求的时间,返回0;若出错,返回-1

reqtp参数用秒和纳秒来指定需要休眠的时间长度。如果某个信号中断了休眠间隔,进程并没有终止,remtp参数指向的timespec结构就会被设置为未休眠完的时间长度。如果对未休眠完的时间并不感兴趣,可以设置为NULL

随着多个系统时钟的引入,需要使用相对于特定时钟的延迟时间来挂起调用线程。clock_nanosleep函数提供了这种功能。

#include <time.h>
int clock_nanosleep(clockid_t clock_id, int flags, const  struct timespec *reqtp, struct timespec *remtp);
返回值:若休眠要求的时间,返回0;若出错,返回错误码。

clock_id参数指定了计算延迟时间基于的时钟。flags参数用于控制延迟是相对的还是绝对的。flags为0时表示休眠时间是相对的,如果flagsTIMER_ABSTIME,表示休眠时间是绝对的。其他的参数reqtpremtp,与nanosleep函数中相同。但是,使用绝对时间时,remtp参数未使用,因为不必要。在时钟到达指定的绝对时间值以前,可以为其他的clock_nanosleep调用复用reqtp参数相同的值。

`

clock_id参数指定了计算延迟时间基于的时钟。flags参数用于控制延迟是相对的还是绝对的。flags为0时表示休眠时间是相对的,如果flagsTIMER_ABSTIME,表示休眠时间是绝对的。其他的参数reqtpremtp,与nanosleep函数中相同。但是,使用绝对时间时,remtp参数未使用,因为不必要。在时钟到达指定的绝对时间值以前,可以为其他的clock_nanosleep调用复用reqtp参数相同的值。

注意: 除了出错返回,调用clock_nanosleep(CLOCK_REALTIME, 0, reqtp, remtp); 和调用 nanosleep(reqtp, remtp);效果相同。使用相对休眠时间的问题是对于那些对休眠精度有要求的应用来说,相对休眠时间会导致实际休眠时间比要求的长,当采用绝对时间时,这样却可以很好的改善精度。

最后

以上就是开心网络为你收集整理的信号之函数system、sleep、nanosleep以及clock_nanosleep的全部内容,希望文章能够帮你解决信号之函数system、sleep、nanosleep以及clock_nanosleep所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(71)

评论列表共有 0 条评论

立即
投稿
返回
顶部