linux alarm 能在线程中用吗

作者&投稿:集蒲 (若有异议请与网页底部的电邮联系)
linux sigsuspend 能用在线程里面吗~

程序启动默认主线程在运行,要想有其他线程你必须手动创建,线程之间没用没用主从说法,你要判断线程是不是main线程,可以::syscall(SYS_gettid)==getpid()来判断,判断线程的tid是否等于该进程的id。

Linux实际上没有真正线程的概念,pthread库中的“线程”被许多人称作“轻量级的进程",内核负责调度所有的进程,且在内核眼里被我们看做线程的东西与普通进程是无差别的。
sleep函数休眠的是当前进程,而pthread库中的“线程”事实上就是进程,因此该函数的作用域就是这个“线程”。

  不管是在进程还是线程,很多时候我们都会使用一些定时器之类的功能,这里就定时器在多线程的使用说一下。首先在linux编程中定时器函数有alarm()和setitimer(),alarm()可以提供一个基于秒的定时功能,而setitimer可以提供一个基于微妙的定时功能。

  alarm()原型:
  #include <unistd.h>
  unsigned int alarm(unsigned int seconds);

  这个函数在使用上很简单,第一次调用这个函数的时候是设置定时器的初值,下一次调用是重新设置这个值,并会返回上一次定时的剩余时间。

  setitimer()原型:
  #include <sys/time.h>
  int setitimer(int which, const struct itimerval *value,struct itimerval *ovalue);

  这个函数使用起来稍微有点说法,首先是第一个参数which的值,这个参数设置timer的计时策略,which有三种状态分别是:

  ITIMER_REAL:使用系统时间来计数,时间为0时发出SIGALRM信号,这种定时能够得到一个精准的定时,当然这个定时是相对的,因为到了微秒级别我们的处理器本身就不够精确。

  ITIMER_VIRTUAL:使用进程时间也就是进程分配到的时间片的时间来计数,时间为0是发出SIGVTALRM信号,这种定时显然不够准确,因为系统给进程分配时间片不由我们控制。

  ITIMER_PROF:上面两种情况都能够触发

  第二个参数参数value涉及到两个结构体:

  struct itimerval {
  struct timeval it_interval; /* next value */
  struct timeval it_value; /* current value */
  };

  struct timeval {
  long tv_sec; /* seconds */
  long tv_usec; /* microseconds */
  };

  在结构体itimerval中it_value是定时器当前的值,it_interval是当it_value的为0后重新填充的值。而timeval结构体中的两个变量就简单了一个是秒一个是微秒。

  上面是这两个定时函数的说明,这个函数使用本不是很难,可以说是很简单,但是碰到具体的应用的时候可能就遇到问题了,在多进程编程中使用一般不会碰到什么问题,这里说的这些问题主要体现在多线程编程中。比如下面这个程序:

  #include <pthread.h>
  #include <signal.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <sys/time.h>

  void sig_handler(int signo)
  {
  alarm(2);
  printf("alarm signal\n");
  }

  void *pthread_func()
  {
  alarm(2);
  while(1)
  {
  pause();
  }
  }

  int main(int argc, char **argv)
  {
  pthread_t tid;
  int retval;

  signal(SIGALRM, sig_handler);

  if((retval = pthread_create(&tid, NULL, pthread_func, NULL)) < 0)
  {
  perror("pthread_create");
  exit(-1);
  }

  while(1)
  {
  printf("main thread\n");
  sleep(10);
  }
  return 0;
  }
  这个程序的理想结果是:
  main thread
  alarm signal
  alarm signal
  alarm signal
  alarm signal
  alarm signal
  main thread
  可事实上并不是这样的,它的结果是:
  main pthread
  alarm signal
  main pthread
  alarm signal
  main pthread

  为什么会出现这种情况呢?是因为发送给工作线程的信号中断的主线程的sleep,并且这个中情况只影响主线程而不会影响到其他的工作线程。我们怎么才能解决这种问题呢,最简单的方法是修改这个程序,修改这个线程主线程使用alarm,工作线程使用sleep。这样就能够达到我们的要求,但是有时候有不能简单的这样操作。所以我们就需要进一步的修改我们的程序。在这里我第一个想到的是使用signal(SIGALRM, SIG_IGN),可是这个是设置整个进程对这个信号的响应方式,经过测试也确实不能完成我期望的功能,那么怎么办呢?有这样一个函数pthread_sigmask,线程中的信号屏蔽,函数的原型及相关函数为:

  #include <signal.h>
  int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
  函数中第一个参数how有三个值SIG_BLOCK、SIG_SETMASK和SIG_UNBLOCK这里我们是用第二个值SIG_SETMASK
  int sigemptyset(sigset_t *set); /*清除信号集合set*/
  int sigaddset(sigset_t *set, int signum); /*添加信号signum到信号集set中*/
  然后我们改造我们的程序为:
  #include <pthread.h>
  #include <signal.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <sys/time.h>

  void sig_handler(int signo)
  {
  alarm(2);
  printf("alarm signal\n");
  }

  void *pthread_func()
  {
  alarm(2);
  while(1)
  {
  pause();
  }
  }

  int main(int argc, char **argv)
  {
  pthread_t tid, tid_1;
  int retval;

  signal(SIGALRM, sig_handler);

  if((retval = pthread_create(&tid, NULL, pthread_func, NULL)) < 0)
  {
  perror("pthread_create");
  exit(-1);
  }

  sigset_t sigset;
  sigemptyset(&sigset);
  sigaddset(&sigset, SIGALRM);
  pthread_sigmask(SIG_SETMASK,&sigset,NULL);

  while(1)
  {
  printf("main pthread\n");
  sleep(10);
  }
  return 0;
  }

  这个时候我们就能够看到我们想要的结果了。

  这里再附一个setitimer的使用范例:

  #include <pthread.h>
  #include <signal.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <sys/time.h>

  struct itimerval timerval;
  void sig_handler(int signo)
  {
  printf("alarm signal\n");
  }
  void *pthread_func()
  {

  setitimer(ITIMER_REAL, &timerval, NULL);
  while(1)
  {
  pause();
  }
  }

  int main(int argc, char **argv)
  {
  pthread_t tid;
  int retval;
  timerval.it_interval.tv_sec = 2;
  timerval.it_interval.tv_usec = 0;
  timerval.it_value.tv_sec = 2;
  timerval.it_value.tv_usec = 0;

  signal(SIGALRM, sig_handler);

  if((retval = pthread_create(&tid, NULL, pthread_func, NULL)) < 0)
  {
  perror("pthread_create");
  exit(-1);
  }

  sigset_t sigset;
  sigemptyset(&sigset);
  sigaddset(&sigset, SIGALRM);
  pthread_sigmask(SIG_SETMASK,&sigset,NULL);

  while(1)
  {
  printf("main thread\n");
  sleep(5);
  }
  return 0;
  }

肯定可以啊


库车县13931113697: linux alarm 能在线程中用吗 -
桑泼石杉: 不管是在进程还是线程,很多时候我们都会使用一些定时器之类的功能,这里就定时器在多线程的使用说一下.首先在linux编程中定时器函数有alarm()和setitimer(),alarm()可以提供一个基于秒的定时功能,而setitimer可以提供一个基于微妙的...

库车县13931113697: Linux 的多线程编程中,如何给线程发信号 -
桑泼石杉: 不管是在进程还是线程,很多时候我们都会使用一些定时器之类的功能,这里就定时器在多线程的使用说一下.首先在linux编程中定时器函数有alarm()和setitimer(),alarm()可以提供一个基于秒的定时功能,而setitimer可以提供一个基于微妙的...

库车县13931113697: linux 线程中怎么实现msgrcv超时 -
桑泼石杉: 如果只有一个线程使用 alarm,可以尝试其他所有线程 sigprocmask 阻塞 SIGALRM,然后仅打开 msgrcv 的线程?

库车县13931113697: linux:在main函数中创建了两个线程,那么谁是主线程,是main函数吗,还是其他的? -
桑泼石杉: 是main函数,因为main函数是一个函数的开头,只有它能调用其它函数,而相反则不行.

库车县13931113697: linux下php是否可以多线程 -
桑泼石杉: 可以通过 pcntl 扩展 实现 ...但windows 下无法运行...web模式下. 也不好运行....用在CLI模式下倒是没问题.

库车县13931113697: linux 可以在线程中再创建线程吗 -
桑泼石杉: 创建线程一般都是在主线程里面创建,因为在主线程里面能够对线程进行管理控制,而且还有很重要的一点,就是linux编程中使用线程的好处是可以共享变量,这在主线程的main函数里面更加方便,所以没有在线程中再创建线程的用法.既然想在线程中再创建线程,为何不用fork复制进程呢,linux的进程开销是非常小的.

库车县13931113697: 可以在线程 中创建进程吗 -
桑泼石杉: 线程可以创建线程,像Java中,main函数就是一个线程来的,可以在main中创建线程.但是,线程应该不能创建进程.因为进程比线程要宏观得多.

库车县13931113697: linux 管道可用在线程间吗 -
桑泼石杉: linux下是可以通过管道进行线程间通信的 参考:http://blog.csdn.net/robertkun/article/details/8095331

库车县13931113697: linux 在线程中可以在创建一个线程么 -
桑泼石杉: gcc xxx.c -lpthread 其中的-l是指包含的lib库,具体写法可以man gcc看下 多线程函数除了要包含头文件pthread.h外还必须要包含lib库pthread pthread_create是创建线程,但具体的线程里面做什么事是在void *create(void *arg)里,这个函数名是自...

库车县13931113697: linux下main()中新建一个线程,延时问题? -
桑泼石杉: 你对sleep可能有些误解,sleep本身就是使进程睡眠,睡眠的线程不会去占用CPU的.对于一个正在运行的线程来说,他最主要占用的资源就是CPU运行时间和内存.既然SLEEP使其放弃对CPU的进程权限(意思是这段时间内,他不会到CPU...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网