⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 2.html

📁 网上一个牛人整理的关于linux内核编译
💻 HTML
📖 第 1 页 / 共 5 页
字号:
  int pri      = param-&gt;priority;<br>
  attr-&gt;start    =param-&gt;start; /* 线程开始参数 */<br>
  attr-&gt;period    = param-&gt;period; /*线程的周期 */<br>
  attr-&gt;deadline   = param-&gt;deadline; /* 线程运行的最终时限 */<p>
2.3.10得到线程调度的参数<br>
说明:在OSKit中,每个线程都有其自身的调度方式,换句话说,就是线程的调度方式仿佛是线程的一个属性,在创建线程的时候就随线程被规定了,所以调度程序可以通过下面的函数来得到某个线程的调度算法和此时它的优先级。<br>
intpthread_attr_getschedparam ( pthread_attr_t *attr, struct sched_param *param)<br>
  param-&gt;priority = attr-&gt;priority;<p>
2.3.11设置线程调度策略<br>
说明:在某些方面,线程的调度策略的确很像线程的属性,但它却是可以在调度中被更改的,系统可以调用此函数完成对线程调度策略的重定义。这样的规定,使得线程调度灵活了许多,当然这种灵活是用增加系统开销的代价换回来的,但却是值得的。<br>
intpthread_attr_setschedpolicy ( pthread_attr_t *attr, int policy )<br>
  switch(policy) {<br>
    case SCHED_FIFO:      /* 先到先处理 */<br>
    caseSCHED_RR:       /* 时间片轮转 */<br>
    case SCHED_EDF       /* 先死先处理 */<br>
    caseSCHED_RMS:       /* 效率优先 */<br>
       attr-&gt;policy = policy;<br>
break;<br>
    case SCHED_DECAY:<br>
       printf(&quot;pthread_attr_setschedpolicy:&quot;<br>
        &quot;SCHED_DECAY not supported yet\n&quot;);<br>
  }<p>
2.3.12得到线程调度策略<br>
说明:负责调度的线程通过该函数得到被调度线程的调度策略,然后再根据此时系统内的情况,决定是否改变其调度算法。<br>
intpthread_attr_getschedpolicy ( const pthread_attr_t *attr, int *policy)<br>
  *policy = attr-&gt;policy;<p>
2.3.13设置堆栈地址<br>
说明:调用此函数,可以实现对线程属性堆栈的底层操作,即设置指向该堆栈的指针,并保存起来,为以后的操作奠定基础。<br>
intpthread_attr_setstackaddr ( pthread_attr_t *attr, oskit_u32_t stackaddr)<br>
  attr-&gt;stackaddr = stackaddr;<p>
2.3.14 得到堆栈的地址<br>
说明:返回指向线程属性堆栈的指针。<br>
intpthread_attr_getstackaddr(const pthread_attr_t *attr, oskit_u32_t*stackaddr)<br>
  *stackaddr = attr-&gt;stackaddr;<p>
2.3.15设置堆栈的大小<br>
说明:由于系统中的线程功能、大小各不相同,所以其属性堆栈的大小也不尽相同,调用此函数可以设置线程属性堆栈大小。<br>
intpthread_attr_setstacksize ( pthread_attr_t *attr, size_t stacksize)<br>
  attr-&gt;stacksize = stacksize;<p>
2.3.16 得到堆栈的大小<br>
说明:返回某个线程堆栈的大小。<br>
int pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *stacksize )<br>
  *stacksize =attr-&gt;stacksize;<p>
2.3.17设置线程的优先级<br>
说明:在操作系统的线程调度中,优先级调度的使用最为广泛,OSKit定义了下面的函数来规定线程的优先级。<br>
intoskit_pthread_attr_setprio ( pthread_attr_t *attr, int pri)<br>
  attr-&gt;priority = pri;<p>
2.3.18准备接受调度<br>
说明:由于多态性原因,不是所有的线程都要参与调度,只是某些线程参加,所以,系统必须调用此函数,告诉该线程准备参加调度,而被调度的方式在上边的几个函数里已经规定好了。<br>
intpthread_attr_setopaque ( pthread_attr_t *attr, oskit_u32_t opaque)<br>
  attr-&gt;opaque = opaque;<p>
2.3.19 声明要进行调度的线程<br>
说明:调用此函数是为了告诉系统,哪些线程是要被调度的。<br>
intpthread_attr_setscheduler ( pthread_attr_t *attr, pthread_t tid)<br>
  attr-&gt;scheduler = tid;<p>
2.3.20设置mutex的属性<br>
说明:在OSKit中,广泛使用了mutex,主要是为了更好的使用临界资源,有效地避免了死锁,换句话说,mutex就像临界资源的数量一样,线程对其进行PV操作。而当一个线程占有了一个mutex,并且在没释放它之前该线程又创建了子线程,此时,子线程理所当然地从父线程手中继承了mutex的所有权,OSKit定义了下面的函数来实现所叙述的功能。<br>
intpthread_mutexattr_init ( pthread_mutexattr_t *attr)<br>
  attr-&gt;priority_inherit = PTHREAD_PRIO_NONE; /* THREAD_PRIO_NONE=0 */<p>
2.3.21撤销mutex的属性<br>
说明:当占有mutex的线程放弃了它的时候,调用该函数来撤销mutex的属性。<br>
intpthread_mutexattr_destroy ( pthread_mutexattr_t *attr )<br>
  memset((void *)attr, -1, sizeof(*attr));<p>
2.3.22设置muxtex的协议<br>
说明:mutex的使用并不是简单的占用与撤销,OSKit还提供了更加完善的mutex协议,它根据inherit的不同,将mutex多样化。<br>
intthread_mutexattr_setprotocol ( pthread_mutexattr_t *attr, int inherit)<br>
  switch (inherit) {<br>
    case PTHREAD_PRIO_NONE:<br>
    casePTHREAD_PRIO_INHERIT:<br>
      attr-&gt;priority_inherit =inherit;<br>
      break;<br>
    default:<br>
      returnEINVAL;<br>
  }<br>
注:在线程调度时,根据mutex协议产生mutex变量,将线程按照优先级排队<p>
2.3.23 得到线程调度的mutex协议<br>
说明:好像对协议的解析一样,调用此函数,可以返回该线程的mutex。<br>
intpthread_mutexattr_getprotocol ( const pthread_mutexattr_t *attr, int*inherit)<br>
  *inherit = attr-&gt;priority_inherit;<p>
2.3.24设置mutex的种类<br>
说明:mutex在OSKit中是可以多种多样的,通过调用下面的函数,可以规定线程到底占用了哪种mutex。<br>
intpthread_mutexattr_settype ( pthread_mutexattr_t *attr, int type )<br>
  switch(type) {<br>
    case PTHREAD_MUTEX_NORMAL: /* 普通 */<br>
    casePTHREAD_MUTEX_ERRORCHECK: /* 错误检查 */<br>
    case PTHREAD_MUTEX_RECURSIVE: /* 递归*/<br>
    case PTHREAD_MUTEX_DEFAULT: /* 默认 */<br>
      attr-&gt;type =type;<br>
      break;<br>
    default:<br>
      return EINVAL;<br>
  }<p>
2.3.25得到mutex的类型<br>
说明:当系统想要知道某个线程占用的是什么类型的mutex时,调用此函数来返回mutex的类型。<br>
intpthread_mutexattr_gettype ( const pthread_mutexattr_t *attr, int *type)<br>
  *type = attr-&gt;type;<p>
<br>
本 章 小 结<p>
本章从线程的创建、存储和数据结构到各种属性以及对它们的操作(设置、撤销和得到)入手,系统地阐述了OSKit线程机制的根源--线程初始化。<p>
在第一节主要从三个角度归纳了OSKit中线程所涉及的概念,它们是创建、存储以及线程的数据结构。第二节中以源代码中的/pthreads/pthread_creat.c 为例,说明了第一节中概念的具体实现。第三节以源代码中的 /pthreads/pthread_attr.c为例,说明了Oskit对线程属性的全部操作,包括线程初始化的数据结构、属性的撤销、线程间关系、对mutex的操作以及对属性堆栈的操作等。<p>
<p>



<center><A HREF="#Content">[目录]</A></center>
<hr><br><A NAME="I560" ID="I560"></A><center><b><font size=+2>第三章 线程通信分析</font></b></center><br>
《OSKit的线程机制 第三章》<p>
<p>
<br>
OSKit的线程机制 第三章2000年12月25日22:11<p>
<br>
作 者: 汤海京<p>
<br>
导师:陈朔鹰<p>
<br>
第三章 线程通信分析<p>
<br>
众所周知,在Linux中,进程为了能在同一项任务上协调工作,彼此之间必须能够进行通信。例如,在一个shell管道中,第一个进程的输出必须传输到第二个进程,这样沿着管道传递下去。因此在需要通信的进程之间,应该使用一种结构较好的通信方式。<p>
Linux支持许多不同形式的进程间通信机制,在特定的情况下,它们各有自己的优缺点,如利用管道进行通信的最大缺点就是,只有成为系统调用pipe的进程的子孙后代的进程才可以使用管道,因此,相互无关的进程不能通过管道通信。<p>
OSKit的开发人员们充分考虑了各种通信方式的利弊,扬长避短,采用了如下的两种线程间通信方式:消息队列和信号量。虽然这还有很多不足之处,但较之SystemV以有所改进。<p>
<br>
3.1 线程间通信<p>
3.1.1消息队列<p>
OSKit提供的消息队列机制于UNIX十分相似,一个和多个线程可向消息队列写入消息,而一个或多个线程可从消息队列中读取消息,这种线程间通信的机制就像客户机/服务器一样,客户机向服务器发送请求消息,服务器读取消息并执行相应的请求。<p>
OSKit将消息描述成在内核地址空间的一个内部链表,每一个消息队列由一个IPC标识号唯一的标识。<p>
3.1.2信号<p>
尽管大多数线程间通信是计划好的,但是同时还需要处理不可预知的通信问题。例如,用户使用文本编辑器要求列出一个大文件的全部内容,但随即他认识到该操作并不重要,这是就需要一种方法来中止编辑器的工作,比如说,我们可以按DEL键来实现。按DEL键实际上是向编辑器发送一个信号,编辑器收到此信号便立即停止打印文件的内容。信号还可以用来报告硬件捕获到的特定的中断,如非法指令和浮点运算溢出、超时也通过信号实现的。<p>
在OSKit中,信号是一种重要的线程间通信机制,线程通过信号知道系统中正在出现的事件。信号的一个特点就是它的异步性,这表示线程在它的执行期间的任何时候都可以接受到信号,甚至可能当线程正在执行系统调用的时候接到信号,因此,线程必须随时为相应信号作好准备。<p>
下面我们再谈谈信号的生成与交付,当引起信号的事件首次出现时,就认为信号为线程而生成,也就是说信号被发送到线程。这类事件的例子,包括:时间片到时,终端激活,硬件故障的检测,kill()的调用。在某些情况下,一个事件为多个可以为多个线程生成信号。每个线程采用样应的动作来响应系统定义的每种信号(见信号量表3.1)。<p>
在信号的生成与交付之间,该信号被挂起,但在用户一级是检测不到这个间隔的。每个线程都拥有一个信号掩码(sig_mask),它规定了当前被阻塞而不能交付给线程的信号集。线程的信号掩码是从父线程继承而来的。我前面提到sigaction(),sigprocmask( )和sigsuspend( )函数,都是对信号掩码的操作。<p>
信号的动作与信号有关的动作分为三种:SIG_DFL,SIG_IGN或指向函数的指针。在最开始,进入main()之前,所有信号都将被置成SIG_DFL或SIG_IGN。<p>
(1)SIG_DFL信号专用的默认动作:<br>
  (a)如果默认动作是暂停线程,则该线程的执行被暂时挂起。当线程暂停期间,发送给线程的任何附加信号都不交付,直到该线程开始执行,但是SIGKILL除外。<br>
  (b)把挂起信号的信号动作设置成SIG_DFL,且其默认动作是忽略信号(SIGCHLD)。<p>
(2)SIG_IGN忽略信号<br>
  (a)该信号的交付对线程没有影响<br>
  (b)系统不允许把SIGKILL或SIGTOP信号的动作设置为SIG_DFL<p>
(3)指向函数的指针--捕获信号<br>
  (a)信号一经交付,接收线程就在指定地址上执行信号捕获程序。在信号捕获函数返回后,接受线程必须在被中断点恢复执行。<br>
  (b)用C语言函数调用的方法进入信号捕捉程序:<br>
    void func(signo)<br>
    int signo;<br>
    func()是指定的信号捕捉函数,signo是正被交付信号的编码<br>
  (c)如果SIGFPE,SIGILL或SIGSEGV信号不是由C标准定义的kill()或raise()函数所生成,则从信号SIGFPE,SIGILL,SIGSEGV的信号捕获函数正常返回后线程的行为是未定义的。<br>
  (d)系统不允许线程捕获SIGKILL和SIGSTOP信号。<br>
  (e)如果线程为SIGCHLD信号建立信号捕获函数,而该线程有未被等待的以终止的子线程时,没有规定是否要生成SIGCHLD信号来指明那个子线程。<p>
每一种信号都被OSKit给予了一个符号名,对于32位的i386平台而言,一个字32位,因而信号有32种。下面的表给出了常用的符号名、描述和它们的信号值。<p>
符号名  信号值描述                是否符合POSIX<br>
SIGHUP  1   在控制终端上检测到挂断或控制线程死亡  是<br>
SIGINT  2   交互注意信号              是<br>
SIGQUIT3   交互中止信号              是<br>
SIGILL  4   检测到非法硬件的指令          是<br>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -