EDU511 国际专业IT教育服务门户 |
|
|
Solaris2.4 多线程编程指南4--操作系统编程日期:08-06-02 22:40:25 点击: 来源:中讯IT 4. 操作系统编程 本章讨论多线程编程如何和操作系统交互,操作系统作出什么改变来支持多线 程。 进程--为多线程而做的改动 警告(alarm), 计数器(interval timer), 配置(profiling) 全局跳转--setjmp(3C) 和longjmp(3C) 资源限制 LWP和调度类型 扩展传统信号 I/O 问题 4.1进程--为多线程而做的改变 4.1.1复制父线程 fork(2) 用fork(2)和fork1(2)函数,你可以选择复制所有的父线程到子线程,或者子 线程只有一个父线程???。 Fork()函数在子进程中复制地址空间和所有的线程(和LWP)。这很有用,例如, 如果子进程永远不调用exec(2)但是用父进程地址空间的拷贝。 为了说明,考虑一个父进程中的线程--不是调用fork()的那个--给一个互斥锁 加了锁。这个互斥锁被拷贝到子进程当中,但给互斥锁解锁的线程没有被拷贝。所 以子进程中的任何试图给互斥锁加锁的线程永久等待。为了避免这种情况,用fork() 复制进程中所有的线程。 注意,如果一个线程调用fork(),阻塞在一个可中断的系统调用的线程将返回 EINTR。 Fork1(2) Fork1(2) 函数在子线程中复制完全的地址空间,但是仅仅复制调用fork1()的 线程。这在子进程在fork()之后立即调用exec()时有用。在这种情况下,子进程不 需要复制调用fork(2)函数的那个线程以外的线程。 在调用fork1()和exec()之间不要调用任何库函数--库函数也许会使用一个由 多个线程操作的锁。 *Fork(2)和fork1(2)的注意事项 对于fork()和fork1(),在调用之后使用全局声明时要小心。 例如,如果一个线程顺序地读一个文件而另外一个线程成功地调用了fork(), 每一个进程都有了一个读文件的线程。因为文件指针被两个线程共享,父进程得到 一些数据,而子进程得到另外一些。 对于fork()和fork1(),不要创建由父进程和子进程共同使用的锁。这仅发生在 给锁分配的内存是共享的情况下(用mmap(2)的MAP_SHARED声明过)。 Vfork(2) Vfork(2)类似于fork1(),只有调用线程被拷贝到子进程当中去。 注意,子进程中的线程在调用exec(2)之前不要改变内存。要记住vfork()将父 进程的地址空间交给子进程。父进程在子进程调用exec()或退出后重新获得地址空 间。子进程不改变父进程的状态是非常重要的。 例如在vfork()和exec()之间创建一个新线程是危险的。 4.1.2执行文件和终止进程 exec(2)和exit(2) exec(2)和exit(2)调用和单线程的进程没有什么区别,只是它们破坏所有线程 的地址空间。两个调用在执行资源(以及活动线程)被破坏前阻塞。 如果exec()重建一个进程,它创建一个LWP。进程从这个初始线程开始执行程序。 象平时一样,如果初始线程返回,它调用exit()来破坏整个进程。 如果所有线程退出,进程用0值退出。 4.2 Alarms(闹钟???), Interval Timers(定时器), and Profiling(配置) 每个LWP有一个唯一的实时的定时器和一个绑定在LWP上的线程的闹钟。定时器 和闹钟在到时间时向线程发送信号。 每个LWP有一个虚拟时间或一个配置定时器,绑定在该LWP上的线程可以使用它 们。如果虚拟定时器到时间,它向拥有定时器的LWP发送信号SIGVTALRM或SIGPROF, 发送哪一个视情况而定。 你可以用profil(2)给每一个LWP进行预配置,给每个LWP私有的缓冲区或者一个 LWP共享的缓冲区。配置数据按LWP用户时间的每一个时钟单位更新。在创建LWP时配 置状态被继承。 4.3非本地跳转--setjmp(3C)和longjmp(3C) setjmp()和longjmp()的使用范围限制在一个线程里,在大多数情况下是合适的。 然而,只有setjmp()和longjmp()在同一个线程里,线程才能对一个信号执行longjmp()。 4.4资源限制 资源限制在整个进程内,每个线程都可以给进程增加资源。如果一个线程超过 了软资源限制,它将发出相应的信号。进程内可用的资源总量可以由getrusage(3B) 获得。 4.5 LWP和调度类型 Solaris 内核有3种进程调度类型。最高优先级的是实时(realtime RT)。其次 是系统(system)。系统调度类型不能在用户进程中使用。最低优先级的是分时 (timeshare TS),它也是缺省类型。 调度类型在LWP内维护。如果一个进程被创建,初始LWP继承父进程的调度类型和 优先级。如果有跟多的LWP被创建来运行非绑定线程,它们也继承这些调度类型和优先 级。进程中的所有非绑定线程有相同的调度类型和优先级。 每个调度类型按照调度类型的配置优先级,把LWP的优先级映射到一个全体的分配 优先级。??? 绑定线程拥有和它们绑定的LWP相同的调度类型和优先级。进程中的每个绑定线程 有一个内核可以看到的调度类型和优先级。系统按照LWP来调度绑定线程。 调度类型用priocntl(2)来设置。前两个参数的指定决定了是只有调用的LWP还是 一个或多个进程所有的LWP都被影响。第三个参数是一个指令,它可以是以下值之一。 · PC_GETCID--获得指定类型的类型号和类型属性 · PC_GETCLINFO--获得指定类型的名称和类型属性 · PC_GETPARMS--获得类型标识和进程中,LWP,或者一组进程的因类型而异 的调度参数 · PC_SETPARMS--设置类型标识和进程中,LWP,或者一组进程的因类型而异 的调度参数 用priocntl()仅限于绑定线程。为了设置非绑定线程的优先级,使用thr_setprio(3T)。 4.5.1分时调度 分时调度将执行资源公平地分配给各进程。内核的其他部分可以在短时间内独占 处理器,而不会使用户感到响应时间延长。 Priocntl(2)调用设置一个或多个线程的nice(2)级别。Priocntl()影响进程中所有 的分时类型的LWP的nice级别。普通拥护的nice()级别从0到20,而超级用户的进程从 -20到20。值越小,级别越高。 分时LWP的分配优先级根据它的LWP的CPU使用率和它的nice()级别来确定。Nice() 级别指定了在进程内供分时调度器参考的相对优先级。LWP的nice()值越大,所得的执 行资源越少,但不会为0。一个执行的多的LWP会被赋予比执行的少的LWP更小的优先级。 4.5.2实时调度 实时类型可以被整个进程或进程内部的一个或多个线程来使用。这需要超级用户 权限。与分时类型的nice(2)级别不同,标识为实时的LWP可以被独立或联合地分配优先 级。一个priocntl(2)调用影响进程中所有实时的LWP的属性。 调度器总是分配最高优先级的实时LWP。如果一个高优先级的LWP可运行,它将打断 低优先级的LWP。一个有先行权(preempt)的LWP被放置在该等级队列的头上。一个实 时(RT)的LWP保持控制处理器,直到被其他线程中断时挂起,或者实时优先级改变。 RT类型的LWP对TS类型的进程有绝对的优先权。 一个新的LWP继承父线程或LWP的调度类型。一个RT类型的LWP继承其父亲的时间片, 不管它是有限还是无限的。一个有有限时间片的LWP持续运行直到结束,阻塞(例如等 待一个I/O事件),被更高优先级的实时进程中断,或者时间片用完。一个拥有无限时 间片的进程则不存在第四种情况(即时间片用完)。 4.5.3 LWP调度和线程绑定 · 线程库自动调节缓冲池中LWP的数量来运行非绑定线程。其目标是: 避免程序因为缺少没有阻塞的LWP而阻塞。 例如,如果可运行的非绑定线程比LWP多而所有的活动线程在内核中处于无限等待 的阻塞状态,进程不能继续,知道一个等待的线程返回。 · 有效利用LWP 例如,如果线程库给每个线程创建一个LWP,许多LWP通常处于闲置状态,而操作 系统反而被没用的LWP耗尽资源。 要记住,LWP是按时间片运行的,而不是线程。这意味着如果只有一个LWP,则进程 内部没有时间片--现成运行直到阻塞(通过线程间同步),被中断,或者运行结束。 可以用thr_setprio(3T)来为线程分配优先级:只有在没有高优先级的非绑定线程 可用时,LWP才会被分配给低优先级的线程。当然,绑定线程不会参与这种竞争,因为 它们有自己的LWP。 把线程绑定到LWP上可以精确地控制调度。???但这种控制在很多非绑定线程竞 争一个LWP是不可能的。 实时线程可以对外部事件有更快的反应。考虑一个用于鼠标控制的线程,它必须对 鼠标事件及时作出反应。通过绑定一个线程到LWP上,保证了在需要时会有LWP可用。通 过将LWP设定为实时调度类型,可以保证LWP对LWP事件作出快速响应。 4.5.4信号等待(SIGWAITING)--给等待线程创建LWP 线程库通常保证在缓冲池内有足够的LWP保证程序运行。如果进程中所有的LWP处 于无限等待的阻塞状态(例如在读中断或网络时阻塞),操作系统给进程发送一个新的 信号,SIGWAITING。这个信号由线程库来控制。如果进程中有一个等待运行的线程,一 个新的LWP被创建并被赋予适当的线程使之执行。 SIGWAITING机制在一个或多个线程处于计算绑定并且有新线程可以执行的情况下。 一个计算绑定线程可以阻止在缺少LWP的情况下有多个可运行的线程启动运行。这可以 通过调用thr_setconcurrency(3T)或者在调用thr_create(3T)时使用THR_NEW_LWP标志。 4.5.5确定LWP的已空闲时间 如果活动线程的数量减少,LWP池中的一些LWP将不再被需要。如果LWP的数量比活动 的线程多,线 ( 责任编辑:) 前一篇: 后一篇: 相关新闻(文章)
|
登录模块加载中...
热点操作系统技术
|
| 友情链接 | |