电子文章 | 电子资料下载 | 家电维修 | 维修资料下载 | 加入收藏 | 全站地图
您现在所在位置:电子爱好者电子文章EDA/PLD线程解析(四)

线程解析(四)

11-20 00:28:14 | http://www.5idzw.com | EDA/PLD | 人气:684
标签:eda技术,eda技术实用教程,http://www.5idzw.com 线程解析(四),http://www.5idzw.com

  作者:曹忠明,www.5idzw.com嵌入式学院讲师。

  一、线程控制

  上一节我们讲了使用互斥量实现线程的同步,这里我们介绍一下另外一种常用的方法,POSIX提供的无名信号量sem,PV原语是对整数计数器信号量sem的操作,P操作判断sem资源数是否为0,不为0则进行P操作,一次P操作可使sem减一,而一次V操作可使sem加一。下面是POSIX提供的一些接口函数:

  1、信号量初始化

  #include <semaphore.h>

  int sem_init(sem_t *sem, int pshared, unsigned int value);

  函数参数:

  sem:信号量

  pshared:一个参数一般为0,表示同一个进程中的线程共享一个信号量。

  value:信号量资源个数

  2、其余函数

  int sem_wait (sem_t* sem);

  int sem_trywait (sem_t* sem);

  int sem_post (sem_t* sem);

  int sem_getvalue (sem_t* sem);

  int sem_destroy (sem_t* sem);

  sem_wait和sem_trywait相当于P操作,它们都能将信号量的值减一,两者的区别在于若信号量的值小于零时,sem_wait将会阻塞进程,而sem_trywait则会立即返回。

  sem_post相当于V操作,它将信号量的值加一,同时发出唤醒的信号给等待的进程(或线程)。

  sem_getvalue 得到信号量的值。

  sem_destroy 摧毁信号量。

  下面用一个例程说明信号量的使用:

  #include <stdio.h>

  #include <pthread.h>

  #include <sys/types.h>

  #include <sys/syscall.h>

  #include <unistd.h>

  #include <semaphore.h>

  sem_t sem;

  pid_t gettid(void)

  {

  return syscall(SYS_gettid);

  }

  void *thread_a(void *arg)

  {

  printf("thread a enter\n");

  sem_wait(&sem); //sem - 1

  printf("thread a P operation\n");

  sleep(10);

  sem_post(&sem); //sem + 1

  printf("thread a V operation\n");

  }

  void *thread_b(void *arg)

  {

  printf("thread b enter\n");

  sem_wait(&sem);     //sem - 1

  printf("thread b P operation\n");

  sleep(10);

  sem_post(&sem); //sem + 1

  printf("thread b V operation\n");

  }

  int main(int argc, char **argv)

  {

  pthread_t tid_a,tid_b;

  int err;

  sem_init(&sem, 0, 1);

  err = pthread_create(&tid_a,NULL,thread_a,NULL);

  if(err < 0)

  {

  perror("pthread_create thread_a");

  }

  err = pthread_create(&tid_b,NULL,thread_b,NULL);

  if(err < 0)

  {

  perror("pthread_create thread_a");

  }

  sleep(30);

  sem_destroy(&sem);

  printf("the main close\n");

  return 0;

  }

  二、POSIX tid和linux tid

  前面我们说创建线程的时候提到一个函数pthread_self,这个函数使POSIX线程库中的一个函数,通过这个函数可以获得线程的ID,可是我们打印出来这个ID会发现这个ID是一个很大的数字。没有得到我们想象的一个数字,其实这个ID是POSIX线程库提供的一个数字,而linux内核中也为这个线程提供了一个ID,这个ID可以通过gettid获得,gettid是linux内核提供的一个系统调用,Glibc没有封装函数,只能通过系统调用实现。

  POSIX:

  #include <pthread>

  pthread_t pthread_self(void);

  linux系统调用:

  #include <sys/types.h>

  #include <sys/syscall.h>

  pid_t gettid(void)

  {

  return syscall(SYS_gettid);

  }

  下面我们通过一个例程看下这两个函数的区别。

  #include <stdio.h>

  #include <pthread.h>

  #include <sys/types.h>

  #include <sys/syscall.h>

  #include <unistd.h>

  pid_t gettid(void)

  {

  return syscall(SYS_gettid);

  }

  void *thread_a(void *arg)

  {

  printf("thread a enter\n");

  pthread_t posix_tid;

  pid_t linux_tid;

  pid_t pid;

  posix_tid = pthread_self();

  linux_tid = gettid();

  pid = getpid();

  printf("pid = %x, posix_tid = %x, linux_tid = %x\n", pid, posix_tid, linux_tid);

  }

  void *thread_b(void *arg)

  {

  printf("thread b enter\n");

  pthread_t posix_tid;

  pid_t linux_tid;

  pid_t pid;

  posix_tid = pthread_self();

  linux_tid = gettid();

  pid = getpid();

  printf("pid = %x, posix_tid = %x, linux_tid = %x\n", pid, posix_tid, linux_tid);

  }

  int main(int argc, char **argv)

  {

  pthread_t tid_a,tid_b;

  int err;

  err = pthread_create(&tid_a,NULL,thread_a,NULL);

  if(err < 0)

  {

  perror("pthread_create thread_a");

  }

  err = pthread_create(&tid_b,NULL,thread_b,NULL);

  if(err < 0)

  {

  perror("pthread_create thread_a");

  }

  sleep(5);

  printf("the main close\n");

  return 0;

  }

  程序运行结果:

  thread a enter

  pid = 3b89, posix_tid = b7fd4b90, linux_tid = 3b8a

  thread b enter

  pid = 3b89, posix_tid = b75d3b90, linux_tid = 3b8b

  the main close

  通过这个函数我们可以发现posix提供的这个ID不是很有规律,而linux内核为线程提供的ID是经跟在主进程进程号的数字,如上面程序中主进程ID为3b89而两个线程的ID分别为3b8a,3b8b。

  “本文由www.5idzw.comhttp://www.5idzw.com提供”


,线程解析(四)
上一篇:线程解析(三)
关于《线程解析(四)》的更多文章