pthread信号

2023-11-16

  信号是典型的异步事件。内核在某个信号出现时有三种处理方式:

  1. 忽略信号,除了SIGKILL和SIGSTOP信号不能忽略外,其他大部分信号都可以被忽略;
  2. 捕捉信号,也就是在信号发生时调用一个用户函数,注意不能捕捉SIGKILL和SIGSTOP;
  3. 执行系统默认动作,注意大多数信号的系统默认动作是终止进程。

         当信号产生以后,对信号采取了动作时,称为向进程“递送”了一个信号,在信号产生(generation)和递送(delivery)之间的时间间隔内,称信号是未决的(pending)。

         进程可以“阻塞”信号,如果为进程产生了一个阻塞的信号,而且对该信号的动作是调用信号处理函数捕捉该信号,或者是系统默认动作,则会为该进程将此信号保持为未决状态,直到a:对此信号解除了阻塞,或者b:对此信号的动作改为忽略。内核在递送一个原来被阻塞的信号给进程时(而不是产生信号时),才决定对它的处理方式,因此,进程在信号被递送之前仍可改变对该信号的动作。

         如果在进程解除某个信号的阻塞之前,该信号发生了多次,则系统可以递送该信号一次或多次。如果递送多次,则称对这些信号进行了排队。但是除非支持POSIX.1实时扩展,否则大多数UNIX并不对信号排队,也就是指递送该信号一次。

         如果有多个信号要递送给一个进程,POSIX.1并未规定这些信号的递送顺序。

         每个进程都有一个信号屏蔽字,它规定了当前要阻塞的信号集。POSIX.1使用数据类型sigset_t表示一个信号集,进程可以调用sigprocmask来检测和更改当前信号屏蔽字。

         对信号的处理是以进程为单位的,也就是说在多线程环境中,信号的处理是进程中所有线程共享的。但是每个线程可以有自己的信号屏蔽字,所以,单个线程可以阻塞某些信号,当某个线程修改了某个信号的处理方式后,所有线程共享这个处理方式的改变。

         进程中的信号是递送到单个线程的。如果信号与硬件故障相关,该信号就被递送到引起该事件的线程中去,而其他信号则被递送到任意一个没有阻塞该信号的线程。sigprocmask的行为在多线程中没有定义,线程必须使用相应的pthread_sigmask。

         除了使用信号处理函数异步的捕捉信号之外,还可以将这种异步行为变得同步,有两种方法:

  1. 调用sigwaitinfo、sigtimedwait或sigwait,这些函数会阻塞调用线程,直到信号集set中的某个信号被递送为止,这些函数都会返回递送信号的信息。
  2. 调用signalfd,它返回一个文件描述符,针对该描述符的read的操作将会阻塞,直到signalfd指定的信号集set中的某个信号递送给调用者为止,此时read返回一个描述该信号的结构。

  信号的行为都是过程范围的,一个程序必须在线程之间协调sigaction的任何使用

  与硬件环境同步的信号包括SIGFPE,SIGSEGV,SIGTRAP他们被送到引起该硬件状况的线程而绝不会传递给其他线程

  不同通过SIGKILL信号来杀死一个线程,也不能通过传送一个SIGTOP信号来停止一个线程

  多线程工作时,任何影响进程的信号仍然影响进程,这意味着向进程或向进程内任何线程传送一个SIGKILL信号(pthread_kill)将终止进程,传送一个SIGSTOP信号将导致所有线程停止直到收到SIGCONT信号,这保证了现存的进程处理函数能够继续工作,否则当你传递一个SIGSTOP信号时进程中大多线程可以运行,这也使用其他信号的默认行为如:SIGSEGV,如果不处理,将终止进程并且产生一个核心文件——它不仅仅产生SIGSEGV线程

信号掩码

  每个线程有自己的信号掩码。如果线程A因为线程B正在处理SIGFPE信号或因为线程C阻塞了SIGFPE信号而不能处理SIGFPE,这不合适。当一个线程被创建时,他继承了创造它的线程信号掩码,如果想在所有地方屏蔽一个信号,则首先在主线程中屏蔽它

int pthread_sigmask(int how,const sigset_t *set,sigset_t *oset);

pthread_kill

  在进程内,一个线程可以通过调用pthread_kill向一个特定的线程包括自己发送信号,不仅需要传递信号数值也要pthread_t,不能向进程外的线程发信号,因为pthread_t只在他创建的进程内有效

int pthread_kill(pthread_t thread,int sig);

  pthread_kill发送的信号:

  1. 如果目标线程被信号屏蔽,他被标记为未解决
  2. 如果线程正在等待sigwait中的信号,线程收到信号
  3. 如果线程没哟屏蔽信号,并且没有在sigwait中阻塞,当前信号将被执行

  除信号处理函数外,信号也影响进程,使用pthread_kill向一特定线程传递SIGKILL信号将杀死整个进程,不仅仅是特定线程。

  raise函数已经传统地被映射到杀死当前进程的函数;即:raise(SIGABRT)通常和kill(getpid(),SIGABRT)一样。对于多线程而言,调用raise的代码可能打算将信号传送到调用的线程而不是一些进程内的线程,raise(SIGABRT)通常和pthread_kill(getpid(),SIGABRT)一样。

  内核调用与信号相比,内核是原子的,因此不会被推迟,write函数不会引起死锁。

  不能推迟一个可能拥有任何资源的线程(如果该资源可能被一些其他线程在推迟线程被恢复之前要求),如果负责将推迟线程恢复的线程首先要获得资源,结果就是死锁。该禁止包括由你调用的库使用的互斥量如malloc或free或stdio使用的互斥量

sigwait和sigwaitifo

  多线程中sigwait总是与异步信号一起工作

  pthreads增加了允许线程代码同步的处理异步信号函数:不允许信号在任意点打断一个线程,线程能够选择同步的接收信号通过调用sigwait或某个兄弟函数来实现。

  调用sigwait等待的信号必须在调用线程中屏蔽,并且通常在所有线程中屏蔽。

  可以创建一个等待一些信号的线程(如:SIGINT)并让他发生时执行一些程序活动,隐含规则是必须在调用sigwait前屏蔽要等待的信号。应该在主线程中,程序的开始屏蔽这些信号,因为信号掩码会继承,所有的线程默认的屏蔽这些信号,这保证信号绝不会被送达除调用sigwait的任何线程。

  信号仅仅被交付一次。如果有两个线程在sigwait上阻塞,只有一个线程收到送给进程的信号,这意味着不能让两个独立的子系统使用sigwait捕获SIGINT,这也意味着信号不会被一个线程的sigwait捕获并送到另外线程的信号处理函数

  sigwait返回个错误是数字来报告错误,两个兄弟函数用errno机制。两个兄弟函数返回收到信号的实时信息siginfo_t,且sigtimedwait在制定时间间隔内没有收到选定信号返回EAGAIN错误

#include <signal.h>
int sigwait(const sigset_t *set, int *sig);
#ifdef _POSIX_REALTIME_SIGNALS
int sigwaitinfo(const sigset_t *set, siginfo_t *info);
int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout);
#endif

  sigwait从set中选择一个未决信号(pending),从进程的未决信号集合中移除该信号,并在sig中返回该信号值。如果set中的所有信号都不是pending状态,则sigwait会阻塞调用它的线程,直到set中的信号变为pending。

         为了避免错误动作发生,线程在调用sigwait之前,必须阻塞那些它正在等待的信号,否则行为是未定义的。sigwait函数会自动取消信号集的阻塞状态,直到有新的信号被递送。在返回之前,sigwait将恢复线程的信号屏蔽字。如果信号在sigwait调用的时候没有被阻塞,则在sigwait调用之前会出现一个时间窗,在这个窗口期,某个信号可能在线程调用sigwait之前就被递送了。

         sigwait只是取消set中信号的阻塞,其他信号则维持原状态,比如,在sigwait调用之前阻塞了所有信号,而set中只包含了SIGINT,则发送SIGABRT也不会有效果。

         如果多个线程在sigwait调用时,等待的是同一个信号,当信号递送的时候,只有一个线程可以从sigwait中返回,具体是那个线程则是未定义的。   

         如果信号被捕获(进程通过使用sigaction建立了一个信号处理程序),而且线程正在sigwait调用中等待同一信号,那么这时将由操作系统实现来决定以何种方式递送信号。在这种情况下,操作系统实现可以让sigwait返回,也可以激活信号处理程序,但不可能出现两者皆可的情况。

         sigwait成功返回0,失败时返回表示错误的值。

         使用sigwait的好处在于它可以简化信号处理,允许把异步产生的信号用同步的方式处理。为了防止信号中断线程,可以把信号加到每个线程的信号屏蔽字中,然后安排专用线程作信号处理。这些专用线程可以进行函数调用,不需要担心在信号处理程序中调用哪些函数是安全的,因为这些函数调用来自正常的线程环境,而非传统的信号处理程序,传统信号处理程序通常会中断线程的正常执行。

  除了返回信息方面,sigwaitinfo的行为基本上与sigwait类似。sigwait在sig中返回触发的信号值;而sigwaitinfo的返回值就是触发的信号值,并且如果info不为NULL,则sigwaitinfo返回时,还会在siginfo_t *info中返回更多该信号的信息,siginfo_t的结构体定义如下:

siginfo_t 
{
    int      si_signo;    /* Signal number */
    int      si_errno;    /* An errno value */
    int      si_code;     /* Signal code */
    int      si_trapno;   /* Trap number that caused hardware-generated signal (unused on most architectures) */
    pid_t    si_pid;      /* Sending process ID */
    uid_t    si_uid;      /* Real user ID of sending process */
    int      si_status;   /* Exit value or signal */
    clock_t  si_utime;    /* User time consumed */
    clock_t  si_stime;    /* System time consumed */
    sigval_t si_value;    /* Signal value */
    int      si_int;      /* POSIX.1b signal */
    void    *si_ptr;      /* POSIX.1b signal */
    int      si_overrun;  /* Timer overrun count; POSIX.1b timers */
    int      si_timerid;  /* Timer ID; POSIX.1b timers */
    void    *si_addr;     /* Memory location which caused fault */
    long     si_band;     /* Band event (was int in glibc 2.3.2 and earlier) */
    int      si_fd;       /* File descriptor */
    short si_addr_lsb;    /*Least significant bit of address (since Linux 2.6.32)*/
}

  比如:info->si_signo是信号值;info->si_code是该信号产生的原因 

        sigtimedwait的行为又与sigwaitinfo的行为类似,只是它多了一个超时参数timeout,也就是可以设置该函数的最大阻塞时间。struct timespec的定义如下:

struct timespec 
{
    long    tv_sec;         /* seconds */
    long    tv_nsec;        /* nanoseconds */
}

  如果该结构体中的成员都置为0的话,则sigtimedwait将会立即返回,此时如果确实有pending信号的话,就返回该信号的信息,否则返回超时错误。

  POSIX没有规定,如果timeout为NULL的话sigtimedwait的行为,Linux下,timeout为NULL时,sigtimedwait的行为与sigwaitinfo是一样的。

signalfd

#include <sys/signalfd.h>
 
int signalfd(int fd, const sigset_t *mask, int flags);

  signalfd用来创建一个接收信号的文件描述符,该文件描述符可用于select、poll和epoll。mask参数中指定了调用者希望接收的信号集,一般而言,信号集中的信号在调用signalfd之前,应该使用sigprocmask进行阻塞,这样这些信号就不会按照原来的处理方式进行处理了。注意不能通过signalfd的文件描述符接收SIGKILL或SIGSTOP信号,如果在mask中指定了这俩信号,则会默认忽略掉。

         如果fd参数为-1,则signalfd创建新的文件描述符,并将信号集mask与该文件描述符相关联。如果fd不为-1,则fd必须是一个已经存在的signalfd文件描述符,mask用于更新与之对应的信号集。

         在Linux2.6.26之前的版本,flags参数是无用的,必须置为0。从Linux2.6.27开始,可以在flags中指定下面的值以改变signalfd的行为:

SFD_NONBLOCK:在新创建的文件描述符上设置O_NONBLOCK文件状态标志;

SFD_CLOEXEC:在新建的文件描述符上设置FD_CLOEXEC标志。

          注意上面的两个标志,都是针对新建描述符而言的(fd为-1),如果是一个已经存在的描述符,设置这两个标志都没有作用(已通过程序验证)。

         signalfd创建描述符支持下列操作:

         read:如果mask中的一个或多个信号是未决状态(pending)的话,则read将会在其buffer参数中返回一个或多个描述信号的signalfd_siginfo结构。read操作尽可能多的返回未决信号,并将其信息填充到buffer。buffer至少应该是sizeof(struct signalfd_siginfo) 个字节,read的返回值就是读取的字节数。

         在read之后,read返回的信号就被消费掉了,不再处于未决状态(也就是不能再由信号处理函数捕捉,也不能使用sigwaitinfo接收)。

         如果mask中的信号都不是未决状态,若文件描述符置为非阻塞的话,read返回EAGAIN错误,否则read会一直阻塞,直到mask中的信号产生。

         select、poll、epoll等:如果mask中有一个或多个信号处于未决状态的话,则这些文件描述符就是可读的,从而可以使得select、poll或者epoll返回。

         close:当不再需要该文件描述符时,应该使用close关闭。与其他文件描述符一样,如果底层signalfd对象关联的所有文件描述符都关闭之后,则该对象的资源就会被内核释放掉

         结构体signalfd_siginfo的定义如下:

struct signalfd_siginfo 
{
    uint32_t ssi_signo;   /* Signal number */
    int32_t  ssi_errno;   /* Error number (unused) */
    int32_t  ssi_code;    /* Signal code */
    uint32_t ssi_pid;     /* PID of sender */
    uint32_t ssi_uid;     /* Real UID of sender */
    int32_t  ssi_fd;      /* File descriptor (SIGIO) */
    uint32_t ssi_tid;     /* Kernel timer ID (POSIX timers) */
    uint32_t ssi_band;    /* Band event (SIGIO) */
    uint32_t ssi_overrun; /* POSIX timer overrun count */
    uint32_t ssi_trapno;  /* Trap number that caused signal */
    int32_t  ssi_status;  /* Exit status or signal (SIGCHLD) */
    int32_t  ssi_int;     /* Integer sent by sigqueue(3) */
    uint64_t ssi_ptr;     /* Pointer sent by sigqueue(3) */
    uint64_t ssi_utime;   /* User CPU time consumed (SIGCHLD) */
    uint64_t ssi_stime;   /* System CPU time consumed (SIGCHLD) */
    uint64_t ssi_addr;    /* Address that generated signal (for hardware-generated signals) */
    uint8_t  pad[X];      /* Pad size to 128 bytes (allow for additional fields in the future) */
};

该结构体中的每个成员都类似于结构体siginfo_t中的成员。对于一个特定的信号,read返回的signalfd_siginfo结构体中,并非所有的成员都是有效的;具体哪些成员是有意义的,可以通过成员ssi_code来检测,该成员类似于siginfo_t中的si_code成员。

         fork之后,子进程拥有了父进程的signalfd文件描述符的副本,在子进程的文件描述符上调用read,将会返回子进程的未决信号。

         类似于其他文件描述符,除非设置了close-on-exec标志,否则signalfd文件描述符在execve之后还是保持打开的,在execve之前可读的信号,在新的进程中依然可读。

         在多线程环境中,signalfd文件描述符与标准的多线程中信号的语义是一样的。也就是说,当一个线程读取signalfd文件描述符时,它会读取到针对该线程的信号,以及针对整个进程的信号。

        调用signalfd成功时,返回一个signalfd文件描述符,该描述符要么是一个新的signalfd描述符(fd为-1的情况下),要么就是fd(fd已经是个有效的signalfd描述符的情况下)。

         调用signalfd错误时,返回-1,并设置相应的errno。

          一个进程可以创建多个signalfd文件描述符,这样可以在不同的signalfd描述符上等待不同的信号。如果多个文件描述符中的mask上具有同一个信号,当信号发生时,所有描述符都变得可读,可以从任意一个描述符读取该信号。这种情况下,如果使用select、poll或者epoll等待这些signalfd描述符,则这些描述符都会变成可读的,从其中之一读取之后,该信号就被消费掉,读取其他的描述符就会阻塞,所以要避免这种情况

SIGEV_THREAD

  当使用aio_read或aio_write时初始化一台异步设备读或写时,程序员指定一个struct aiocb,其中包含了一个struct sigevent成员,接受struct sigevent的其他函数包括timer_create(他创造一个进程范围内的定时器)和sigqueue(他将信号送入进程队列)。

  struct sigevent提供了一种允许程序员指定一个信号是否产生以及如果产生应该使用时什么信号数字的“通知机制”。pthreads增设了一个被称为SIGEV_THREAD的新通知机制,该通知机制使得信号通知函数向线程气势函数一样运行。

  SIGEV_THREAD通知函数可能无法在一个新的线程中实际运行。系统可以排队SIGEV_THREAD事件,在一些内部“服务线程”连续调用起始函数,这种差别对于应用程序而言很难有效的区分,使用系统服务线程要很小心的为通知线程指定属性——调度策略,优先级,竞争范围,最小栈空间。

  对于传统的信号机制如:setitimer,SIGCHLD,SIGINT等,SIGEV_THREAD特性不可用。

timer_t timer_id;
struct itimerspec ts;
struct sigevent se;

se.sigev_notify=SIGEV_THREAD;
se.sigev_value.sival_ptr=&timer_id;
se.sigev_notify_function=timer_fun;//一个指向线程起始函数的指针
//期望的线程创建属性的线程属性对象---pthread_attr_t,如为空,则与将deatchstate属性设置为PTHREAD_CREATE_DETACHED一样
//创建通知线程,这样避免内存泄漏,因为线程标识符不是对任何其他线程来讲都可得到所以说PTHREAD_CREATE_JOINABLE结果是不可知的
se.sigev_notify_attributes=NULL;

ts.it_value.tv_sec=5;
ts.it_value.tv_nsec=0;
ts.it_interval.tv_sec=5;
ts.it_interval.tv_nsec=0;

timer_create(CLOCK_REALTIME,&se,&timer_id);

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

 

转载于:https://www.cnblogs.com/tianzeng/p/9314380.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pthread信号 的相关文章

  • ps aux 和ps -aux和 ps -ef的选择

    Linux中的ps命令是Process Status的缩写 ps命令用来列出系统中当前运行的那些进程 ps命令列出的是当前那些进程的快照 就是执行ps命令的那个时刻的那些进程 如果想要动态的显示进程信息 就可以使用top命令 要对进程进行监
  • nslookup命令详解

    nslookup命令用于查询DNS的记录 查看域名解析是否正常 在网络故障的时候用来诊断网络问题 nslookup的用法相对来说还是蛮简单的 主要是下面的几个用法 1 直接查询 这个可能大家用到最多 查询一个域名的A记录 nslookup
  • InfoQ视频直播分享报名:前贝尔实验室、Oracle架构师为你在线揭秘分布式平台内核...

    报名方式 关注InfoQ微信公众号 ID infoqchina 回复 InfoQ 即可观看在线直播技术分享 分享地点 u0026amp 时间 InfoQ直播微课堂将在熊猫 TV 网站播出 看腻了卖肉的女主播 来看看QCon 的明星讲师如何
  • 程序员的自我修养——链接、装载与库

    1 温故而知新 操作系统概念 北桥 连接高速芯片 系统调用接口 以软件中断的方式提供 如Linux使用0x80号中断作为系统调用接口 多任务系统 进程隔离 设备驱动 直接使用物理内存的弊端 地址空间不隔离 内存使用效率低 程序运行的地址不确
  • 03LinuxC线程学习之线程共享和非共享

    1 线程共享和非共享 1 1 线程共享资源 1 文件描述符表 由于线程间共享进程间的内容 而文件描述符表在主线程的PCB当中 各个线程可以直接去请求访问 所以线程间通信就不需要像进程那样通过管道这些方式通信 2 每种信号的处理方式 即当某个
  • Linux系统如何看目录属于哪个磁盘分区

    Linux是先有目录 再有磁盘分区 df h 目录 例如 没有挂载磁盘的目录 显示在系统盘 root iZ2ze57v3n0zma46zqiq8nZ sh 1 5 5 df h alidata Filesystem Size Used Av
  • 操作系统 段页式存储管理

    一 引入 分页系统是以页面作为内存分配的基本单位 能有效地提高内存利用率 但信息共享等不方便 分段系统是以段作为内存分配的基本单位 它能够更好地满足用户多方面的需要 信息共享 动态链接等 但采用分区方式管理物理内存 仍然存在碎片问题 段页式
  • [架构之路-185]-《软考-系统分析师》-3-操作系统基本原理 - 文件索引表

    目录 一 文件的索引块 二 索引分配表 三 索引表的链接方案 四 多层索引 五 混合索引分配 一 文件的索引块 存放在目录中的文件 并非是文件的真实内容 目录中记录了文件的索引块是几号磁盘块 文件对应的索引表是存放在指定的磁盘块中的 二 索
  • Windows运行常用命令(win+R)

    1 calc 启动计算器 2 notepad 打开记事本 3 write 写字板 4 mspaint 画图板 5 snippingtool 截图工具 支持无规则截图 6 mplayer2 简易widnows media player 7 S
  • OS——文件管理系统磁盘的结构之搞清盘面和柱面

    如上图 每个柱面有三个盘面 即就是3个磁道 柱面可以抽象的理解成是一个套一个的立体的同心圆柱体 例 2019年408真题 磁盘有300个柱面 每个柱面有10个磁道 每个磁道有200个扇区 扇区大小为512B 则磁盘容量 分析 每个柱面有10
  • linux 使用systemctl 启动服务报错: Error: No space left on device

    By default Linux only allocates 8192 watches for inotify which is ridiculously low And when it runs out the error is als
  • 【操作系统】王道考研 p42 段页式管理方式

    段页式管理方式 知识总览 分段 分页管理方式中最大的优缺点 关于段式管理会产生外部碎片 ps 分段管理中产生的外部碎片也可以用 紧凑 来解决 只是需要付出较大的时间代价 分段 分页 段页式管理 示意图 先分段 后分页 段页式管理的逻辑地址结
  • epoll 在客户端断开连接时循环

    我正在尝试使用以下方式实现套接字服务器epoll 我有 2 个线程执行 2 个任务 监听传入的连接 在屏幕上写入客户端发送的数据 对于我的测试 我将客户端和服务器放在同一台计算机上 并运行 3 或 4 个客户端 服务器工作正常 直到我不通过
  • 使用 asyncio 时无法使用 os.fork() 将多个进程绑定到一个套接字服务器

    我们都知道 使用 asyncio 可以显着提高套接字服务器的性能 如果我们能够利用 cpu 中的所有核心 可能通过多处理模块或os fork etc 我现在正在尝试构建一个多核套接字服务器演示 其中一个异步套接字服务器侦听每个核心并全部绑定
  • Linux(13):例行性工作排程

    例行性工程 听谓的排程是将工作安排执行的流程之意 Linux 排程就是透过 crontab 与 at 这两个东西 两种工作排程的方式 一种是例行性的 就是每隔一定的周期要来办的事项 一种是突发性的 就是这次做完以后就没有的那一种 at at
  • Linux(12):磁盘配额(Quota)与进阶文件系统管理

    磁盘配额 Quota 的应用与实作 Quota 的一般用途 针对 www server 例如 每个人的网页空间的容量限制 针对 mail server 例如 每个人的邮件空间限制 针对 file server 例如 每个人最大的可用网络硬盘
  • EPOLLET 的用例是什么? [关闭]

    Closed 这个问题是基于意见的 目前不接受答案 epoll在边缘触发模式下是一个奇怪的野兽 它要求进程跟踪每个受监控 FD 的最后响应是什么 它要求进程必须处理所报告的每个事件 否则我们可能会认为 FD 没有报告任何内容 而实际上它已被
  • 如何构建netty-transport-native-epoll-4.0.32.Final-linux-x86_64.jar?

    我在 netty 中使用本机 epoll 传输 并且能够从存储库下载 netty transport native epoll 4 0 32 jar 不过我还需要 netty transport native epoll 4 0 32 Fi
  • 边缘触发的 epoll 和 oneshot 只报告一次

    我目前正在添加从创建的 sockfdsaccept到具有以下事件的 epoll 实例 const int EVENTS EPOLLET EPOLLIN EPOLLRDHUP EPOLLONESHOT EPOLLERR EPOLLHUP 一旦
  • 如何将 boost::asio 与 Linux GPIO 结合使用

    我有一个单线程 Linux 应用程序 使用 boost asio 进行异步输入 输出 现在我需要扩展此应用程序以读取 GPIO 输入 sys class gpio gpioXX value 可以在边沿触发的 GPIO 输入上使用 boost

随机推荐

  • 常用的OkHttpClient配置项

    OkHttpClient是一个功能强大的HTTP客户端 提供了各种配置选项来满足不同的需求 以下是一些常用的OkHttpClient配置项 连接池 Connection Pool 设置连接池 控制同时允许的最大连接数和连接的空闲时间 con
  • springMVC +Mybatis +spring aop 实现用户系统操作日志记录

    业务场景 业务要求记录用户在系统的操作行为 并保存到数据库当中 1 自定义注解 记录操作日志 import java lang annotation Documented import java lang annotation Elemen
  • 淘宝API接口介绍

    淘宝API接口 Taobao API interface 是淘宝平台进行业务开放的一个重大举措 针对小程序日渐受欢迎的局面 购物软件由于所占空间大 操作流程繁琐已经不占据优势 因此更多线上购物会以小程序的形式进行 而淘宝API接口就是将淘宝
  • UE4-蓝图函数库

    UE4 蓝图函数库 概述 蓝图函数库 Blueprint Function Library 是一个静态函数的合集 提供不与特定游戏性对象绑定的效用功能 即不用绑定到对象身上 再到蓝图中进行调用 可以非常方便的将代码中的函数暴露给所有蓝图使用
  • 图解U-Boot(没有SPL的uboot早期版本):第二阶段源码分析

    原文地址 http blog csdn net ce123 zhouwei article details 7318851 说明 图片上传后有点模糊 可从http download csdn net detail ce123 4112241
  • druid与mysql连接超时的问题

    背景 公司一个项目使用了druid连接池 mysql数据库 生产环境日志偶尔会打印一个错误如下 com mysql jdbc exceptions jdbc4 CommunicationsException Communications l
  • 入门产品经理的7个实用方法

    关注同名公众号 获得更多产品经理知识干货 每天5分钟 你也可以成为优秀的产品经理 你好 我是郭杉 欢迎来到 郭杉 产品经理50讲 第2讲 正式开始今天的内容之前 我想先问你一个问题 你是不是一直苦于想入门但却没有人带 自己摸索却不知如何开始
  • Grafana如何正确配置数据源

    Grafana配置数据源的步骤如下 1 首先选择设置 点击数据源 再选择添加数据源 2 根据需要选择对应的数据库类型 3 输入对应的数据库信息 4 测试数据是否连接成功 5 若发现出现如上错误 更改Encrypt值为disable后 再次测
  • 大数据课程M1——ELK的概述

    文章作者邮箱 yugongshiye sina cn 地址 广东惠州 本章节目的 了解ELK的定义 掌握ELK的使用 一 什么是ELK 1 简介 ELK 是elastic公司提供的一套完整的日志收集以及展示的解决方案 是三个产品的首字母缩写
  • mybatis,#和$的区别

    与 井号与美元符号使用的区别 占位符 表示列值放在等号的右侧 而且使用的是jdbc的preparedStatement效率高没有sql注入的风险 占位符 是表示字符串的连接 使用的是Statement效率低有sql注入风险
  • 均值极差图控制上下限_统计过程控制(SPC)和休哈特控制图之九XbarR(均值极差)控制图...

    期来介绍一下Xbar R 均值 极差 控制图 希望下面分享的能给朋友们理解和应用统计过程控制带来启发和帮助 统计技术本身不会解决质量过程的各种问题 无论如何还是得实际的过程应用中适时结合相应的产品才能发挥效能 以至于把控制图识别出来的问题解
  • Java常用类 学习记录

    String类 关于Java JDK中内置的一个类 java lang String 1 String表示字符串类型 不属于基本数据类型 2 用双引号括起来的 例如 abc def hello world 这3个是String对象 3 双引
  • JDBC(mysql)显式设置serverTimezone的原因和方法

    TOC设置原因和方法 参 自 设置原因和方法 serverTimezone GMT 2B8 jdbc url jdbc mysql localhost 3306 demo serverTimezone UTC characterEncodi
  • python一共有多少代码_Python项目可以有多大?最多可以有多少行代码?

    导读 总是看到有人说 动态一时爽 重构火葬场 然而这世界上有的是著名的开源项目 也有像 Github Instagram 这样流量巨大的知名网站是基于动态语言开发的 经过了这么多年重构 也未听说哪个作者进了火葬场的 不明白这些人是真的不知道
  • 使用腾讯云DNSPod实现动态域名解析DDNS(测试可以用)

    使用原理 DDNS Dynamic Domain Name Server 是动态域名服务的缩写 是将用户的动态IP地址映射到一个固定的域名解析服务上 用户每次连接网络的时候客户端程序就会通过信息传递把该主机的动态IP地址传送给位于服务商主机
  • Unity中实现退出游戏功能

    我们要实现在编辑器环境下退出编辑器 在非编译器环境下退出游戏 提问 如何判断是否在编辑器环境中 如何退出编辑模式 如何退出程序 回答 使用预处理判断当前的环境 常用的预处理标识符 标识符 解释 UNITY EDITOR 只在编辑器中编译 U
  • mysql根据日期倒序_mysql记录根据日期字段倒序输出

    我们知道倒序输出是很简单的 select from table order by id desc 直接这样就可以 那么现在的问题在于日期字段怎么来倒序输出 这里我们用到cast 来将指定的字段转换为我们需要的类型 如下是实际项目中的sql语
  • C/C++项目:谁都爱玩的4399小游戏黄金矿工教程

    黄金矿工中文版 是一款休闲益智小游戏 游戏中你需要看准时机出钩子勾取金子或者砖石来获得金钱的累加 达到一定的金钱数才能够闯关成功 游戏十分经典 强烈推荐大家学会编写这款游戏 休闲时没网也能自己玩哦 黄金矿工道具说明 金块 按大小区分 越大越
  • Robot Framework 企业级自动化测试实战

    一 Robot Framework 变量使用 1 变量简介 变量是Robot Framework的一个不可或缺的特性 它们可以在测试数据的大多数地方使用 最常见的是 它们用于测试用例表和关键字表中关键字的参数 但所有设置都允许在其值中使用变
  • pthread信号

    信号是典型的异步事件 内核在某个信号出现时有三种处理方式 忽略信号 除了SIGKILL和SIGSTOP信号不能忽略外 其他大部分信号都可以被忽略 捕捉信号 也就是在信号发生时调用一个用户函数 注意不能捕捉SIGKILL和SIGSTOP 执行