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

📄 pth.3

📁 Linux下的中文输入法
💻 3
📖 第 1 页 / 共 5 页
字号:
.SpThe disadvantage is that although the general performance is increased,compared to using approaches based on heavy-weight processes, it is decreasedcompared to the matrix-approach above. Because the implicit preemptivescheduling does usually a lot more context switches (every user-space contextswitch costs some overhead even when it is a lot cheaper than a kernel-levelcontext switch) than the explicit cooperative/non\-preemptive scheduling.Finally, there is no really portable \s-1POSIX/ANSI\-C\s0 based way to implementuser-space preemptive threading. Either the platform already has threads,or one has to hope that some semi-portable package exists for it. Andeven those semi-portable packages usually have to deal with assemblercode and other nasty internals and are not easy to port to forthcomingplatforms..PPSo, in short: the matrix-dispatching approach is portable and fast, butnasty to program. The thread scheduling approach is easy to program,but suffers from synchronization and portability problems caused by itspreemptive nature..Sh "The Compromise of Pth".IX Subsection "The Compromise of Pth"But why not combine the good aspects of both approaches while avoidingtheir bad aspects? That's the goal of \fBPth\fR. \fBPth\fR implementseasy-to-program threads of execution, but avoids the problems ofpreemptive scheduling by using non-preemptive scheduling instead..PPThis sounds like, and is, a useful approach. Nevertheless, one has tokeep the implications of non-preemptive thread scheduling in mind whenworking with \fBPth\fR. The following list summarizes a few essentialpoints:.IP "\fBo\fR" 2.IX Item "o"\&\fBPth provides maximum portability, but \s-1NOT\s0 the fanciest features\fR..SpThis is, because it uses a nifty and portable \s-1POSIX/ANSI\-C\s0 approach forthread creation (and this way doesn't require any platform dependentassembler hacks) and schedules the threads in non-preemptive way (whichdoesn't require unportable facilities like \f(CW\*(C`SIGVTALRM\*(C'\fR). On the otherhand, this way not all fancy threading features can be implemented.Nevertheless the available facilities are enough to provide a robust andfull-featured threading system..IP "\fBo\fR" 2.IX Item "o"\&\fBPth increases the responsiveness and concurrency of an event-drivenapplication, but \s-1NOT\s0 the concurrency of number-crunching applications\fR..SpThe reason is the non-preemptive scheduling. Number-crunchingapplications usually require preemptive scheduling to achieveconcurrency because of their long \s-1CPU\s0 bursts. For them, non-preemptivescheduling (even together with explicit yielding) provides only the oldconcept of `coroutines'. On the other hand, event driven applicationsbenefit greatly from non-preemptive scheduling. They have only short\&\s-1CPU\s0 bursts and lots of events to wait on, and this way run faster undernon-preemptive scheduling because no unnecessary context switchingoccurs, as it is the case for preemptive scheduling. That's why \fBPth\fRis mainly intended for server type applications, although there is notechnical restriction..IP "\fBo\fR" 2.IX Item "o"\&\fBPth requires thread-safe functions, but \s-1NOT\s0 reentrant functions\fR..SpThis nice fact exists again because of the nature of non-preemptivescheduling, where a function isn't interrupted and this way cannot bereentered before it returned. This is a great portability benefit,because thread-safety can be achieved more easily than reentrancepossibility. Especially this means that under \fBPth\fR more existingthird-party libraries can be used without side-effects than it's the casefor other threading systems..IP "\fBo\fR" 2.IX Item "o"\&\fBPth doesn't require any kernel support, but can \s-1NOT\s0benefit from multiprocessor machines\fR..SpThis means that \fBPth\fR runs on almost all Unix kernels, because thekernel does not need to be aware of the \fBPth\fR threads (because theyare implemented entirely in user\-space). On the other hand, it cannotbenefit from the existence of multiprocessors, because for this, kernelsupport would be needed. In practice, this is no problem, becausemultiprocessor systems are rare, and portability is almost moreimportant than highest concurrency..Sh "The life cycle of a thread".IX Subsection "The life cycle of a thread"To understand the \fBPth\fR Application Programming Interface (\s-1API\s0), ithelps to first understand the life cycle of a thread in the \fBPth\fRthreading system. It can be illustrated with the following directedgraph:.PP.Vb 10\&             NEW\&              |\&              V\&      +---> READY ---+\&      |       ^      |\&      |       |      V\&   WAITING <--+-- RUNNING\&                     |\&      :              V\&   SUSPENDED       DEAD.Ve.PPWhen a new thread is created, it is moved into the \fB\s-1NEW\s0\fR queue of thescheduler. On the next dispatching for this thread, the scheduler picksit up from there and moves it to the \fB\s-1READY\s0\fR queue. This is a queuecontaining all threads which want to perform a \s-1CPU\s0 burst. There they arequeued in priority order. On each dispatching step, the scheduler alwaysremoves the thread with the highest priority only. It then increases thepriority of all remaining threads by 1, to prevent them from `starving'..PPThe thread which was removed from the \fB\s-1READY\s0\fR queue is the new\&\fB\s-1RUNNING\s0\fR thread (there is always just one \fB\s-1RUNNING\s0\fR thread, ofcourse). The \fB\s-1RUNNING\s0\fR thread is assigned execution control. Afterthis thread yields execution (either explicitly by yielding executionor implicitly by calling a function which would block) there are threepossibilities: Either it has terminated, then it is moved to the \fB\s-1DEAD\s0\fRqueue, or it has events on which it wants to wait, then it is moved intothe \fB\s-1WAITING\s0\fR queue. Else it is assumed it wants to perform more \s-1CPU\s0bursts and immediately enters the \fB\s-1READY\s0\fR queue again..PPBefore the next thread is taken out of the \fB\s-1READY\s0\fR queue, the\&\fB\s-1WAITING\s0\fR queue is checked for pending events. If one or more eventsoccurred, the threads that are waiting on them are immediately moved tothe \fB\s-1READY\s0\fR queue..PPThe purpose of the \fB\s-1NEW\s0\fR queue has to do with the fact that in \fBPth\fRa thread never directly switches to another thread. A thread alwaysyields execution to the scheduler and the scheduler dispatches to thenext thread. So a freshly spawned thread has to be kept somewhere untilthe scheduler gets a chance to pick it up for scheduling. That iswhat the \fB\s-1NEW\s0\fR queue is for..PPThe purpose of the \fB\s-1DEAD\s0\fR queue is to support thread joining. When athread is marked to be unjoinable, it is directly kicked out of thesystem after it terminated. But when it is joinable, it enters the\&\fB\s-1DEAD\s0\fR queue. There it remains until another thread joins it..PPFinally, there is a special separated queue named \fB\s-1SUSPENDED\s0\fR, to wherethreads can be manually moved from the \fB\s-1NEW\s0\fR, \fB\s-1READY\s0\fR or \fB\s-1WAITING\s0\fRqueues by the application. The purpose of this special queue is totemporarily absorb suspended threads until they are again resumed bythe application. Suspended threads do not cost scheduling or eventhandling resources, because they are temporarily completely out of thescheduler's scope. If a thread is resumed, it is moved back to the queuefrom where it originally came and this way again enters the schedulersscope..SH "APPLICATION PROGRAMMING INTERFACE (API)".IX Header "APPLICATION PROGRAMMING INTERFACE (API)"In the following the \fBPth\fR \fIApplication Programming Interface\fR (\s-1API\s0)is discussed in detail. With the knowledge given above, it should nowbe easy to understand how to program threads with this \s-1API\s0. In goodUnix tradition, \fBPth\fR functions use special return values (\f(CW\*(C`NULL\*(C'\fRin pointer context, \f(CW\*(C`FALSE\*(C'\fR in boolean context and \f(CW\*(C`\-1\*(C'\fR in integercontext) to indicate an error condition and set (or pass through) the\&\f(CW\*(C`errno\*(C'\fR system variable to pass more details about the error to thecaller..Sh "Global Library Management".IX Subsection "Global Library Management"The following functions act on the library as a whole.  They are used toinitialize and shutdown the scheduler and fetch information from it..IP "int \fBpth_init\fR(void);" 4.IX Item "int pth_init(void);"This initializes the \fBPth\fR library. It has to be the first \fBPth\fR \s-1API\s0function call in an application, and is mandatory. It's usually done atthe begin of the \fImain()\fR function of the application. This implicitlyspawns the internal scheduler thread and transforms the single executionunit of the current process into a thread (the `main' thread). Itreturns \f(CW\*(C`TRUE\*(C'\fR on success and \f(CW\*(C`FALSE\*(C'\fR on error..IP "int \fBpth_kill\fR(void);" 4.IX Item "int pth_kill(void);"This kills the \fBPth\fR library. It should be the last \fBPth\fR \s-1API\s0 function callin an application, but is not really required. It's usually done at the end ofthe main function of the application. At least, it has to be called from withinthe main thread. It implicitly kills all threads and transforms back thecalling thread into the single execution unit of the underlying process.  Theusual way to terminate a \fBPth\fR application is either a simple`\f(CW\*(C`pth_exit(0);\*(C'\fR' in the main thread (which waits for all other threads toterminate, kills the threading system and then terminates the process) or a`\f(CW\*(C`pth_kill(); exit(0)\*(C'\fR' (which immediately kills the threading system andterminates the process). The \fIpth_kill()\fR return immediately with a returncode of \f(CW\*(C`FALSE\*(C'\fR if it is not called from within the main thread. Else itkills the threading system and returns \f(CW\*(C`TRUE\*(C'\fR..IP "long \fBpth_ctrl\fR(unsigned long \fIquery\fR, ...);" 4.IX Item "long pth_ctrl(unsigned long query, ...);"This is a generalized query/control function for the \fBPth\fR library.  Theargument \fIquery\fR is a bitmask formed out of one or more \f(CW\*(C`PTH_CTRL_\*(C'\fR\fI\s-1XXXX\s0\fRqueries. Currently the following queries are supported:.RS 4.ie n .IP """PTH_CTRL_GETTHREADS""" 4.el .IP "\f(CWPTH_CTRL_GETTHREADS\fR" 4.IX Item "PTH_CTRL_GETTHREADS"This returns the total number of threads currently in existence.  This queryactually is formed out of the combination of queries for threads in aparticular state, i.e., the \f(CW\*(C`PTH_CTRL_GETTHREADS\*(C'\fR query is equal to theOR-combination of all the following specialized queries:.Sp\&\f(CW\*(C`PTH_CTRL_GETTHREADS_NEW\*(C'\fR for the number of threads in thenew queue (threads created via \fIpth_spawn\fR\|(3) but still notscheduled once), \f(CW\*(C`PTH_CTRL_GETTHREADS_READY\*(C'\fR for the number ofthreads in the ready queue (threads who want to do \s-1CPU\s0 bursts),\&\f(CW\*(C`PTH_CTRL_GETTHREADS_RUNNING\*(C'\fR for the number of running threads(always just one thread!), \f(CW\*(C`PTH_CTRL_GETTHREADS_WAITING\*(C'\fR forthe number of threads in the waiting queue (threads waiting forevents), \f(CW\*(C`PTH_CTRL_GETTHREADS_SUSPENDED\*(C'\fR for the number ofthreads in the suspended queue (threads waiting to be resumed) and\&\f(CW\*(C`PTH_CTRL_GETTHREADS_DEAD\*(C'\fR for the number of threads in the new queue(terminated threads waiting for a join)..ie n .IP """PTH_CTRL_GETAVLOAD""" 4.el .IP "\f(CWPTH_CTRL_GETAVLOAD\fR" 4.IX Item "PTH_CTRL_GETAVLOAD"This requires a second argument of type `\f(CW\*(C`float *\*(C'\fR' (pointer to a floatingpoint variable).  It stores a floating point value describing the exponentialaveraged load of the scheduler in this variable. The load is a function fromthe number of threads in the ready queue of the schedulers dispatching unit.So a load around 1.0 means there is only one ready thread (the standardsituation when the application has no high load). A higher load value meansthere a more threads ready who want to do \s-1CPU\s0 bursts. The average load valueupdates once per second only. The return value for this query is always 0..ie n .IP """PTH_CTRL_GETPRIO""" 4.el .IP "\f(CWPTH_CTRL_GETPRIO\fR" 4.IX Item "PTH_CTRL_GETPRIO"This requires a second argument of type `\f(CW\*(C`pth_t\*(C'\fR' which identifies athread.  It returns the priority (ranging from \f(CW\*(C`PTH_PRIO_MIN\*(C'\fR to\&\f(CW\*(C`PTH_PRIO_MAX\*(C'\fR) of the given thread..ie n .IP """PTH_CTRL_GETNAME""" 4.el .IP "\f(CWPTH_CTRL_GETNAME\fR" 4.IX Item "PTH_CTRL_GETNAME"This requires a second argument of type `\f(CW\*(C`pth_t\*(C'\fR' which identifies athread. It returns the name of the given thread, i.e., the return value of\&\fIpth_ctrl\fR\|(3) should be casted to a `\f(CW\*(C`char *\*(C'\fR'..ie n .IP """PTH_CTRL_DUMPSTATE""" 4.el .IP "\f(CWPTH_CTRL_DUMPSTATE\fR" 4.IX Item "PTH_CTRL_DUMPSTATE"This requires a second argument of type `\f(CW\*(C`FILE *\*(C'\fR' to which a summaryof the internal \fBPth\fR library state is written to. The main informationwhich is currently written out is the current state of the thread pool..ie n .IP """PTH_CTRL_FAVOURNEW""" 4.el .IP "\f(CWPTH_CTRL_FAVOURNEW\fR" 4.IX Item "PTH_CTRL_FAVOURNEW"This requires a second argument of type `\f(CW\*(C`int\*(C'\fR' which specified whetherthe \fB\s-1GNU\s0 Pth\fR scheduler favours new threads on startup, i.e., whetherthey are moved from the new queue to the top (argument is \f(CW\*(C`TRUE\*(C'\fR) ormiddle (argument is \f(CW\*(C`FALSE\*(C'\fR) of the ready queue. The default is tofavour new threads to make sure they do not starve already at startup,although this slightly violates the strict priority based scheduling..RE.RS 4.SpThe function returns \f(CW\*(C`\-1\*(C'\fR on error.

⌨️ 快捷键说明

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