Port Windows IPC Apps to Linux, Part 1: Processes and Threads
By Srinivasan S. Muthuswamy, Kavitha Varadarajan2005-06-16
Threads
In Windows, the thread is the basic unit of execution. One or more threads run in the context of the process. The scheduling code is implemented in the kernel. There is no single "scheduler" module or routine.
The Linux kernel uses a process model rather than a threading model. The Linux kernel provides a lightweight process framework for creating threads; the actual thread implementation is in the user space. There are various threading libraries available (LinuxThreads, NGPT, NPTL, and so on) in Linux. The information in this article is based on the LinuxThreads library, but the information here is also applicable to Red Hat's Native POSIX Threading Library (NPTL).
This section describes threading in Windows and in Linux. It covers the calls for creating a thread, setting its attributes, and changing its priority.
| Windows | Linux | Classification |
CreateThread | pthread_createpthread_attr_initpthread_attr_setstacksizepthread_attr_destroy | Mappable |
ThreadExit | pthread_exit | Mappable |
WaitForSingleObject | pthread_joinpthread_attr_setdetachstatepthread_detach | Mappable |
SetPriorityClassSetThreadPriority | setprioritysched_setschedulersched_setparampthread_setschedparampthread_setschedpolicypthread_attr_setschedparampthread_attr_setschedpolicy | Context Specific |
Creating a thread
In Windows, you can use CreateThread() to create a thread to execute under the virtual address space of the calling process.
|
lpThreadAttributes is a pointer to the thread attributes that determines whether the thread handle can be inherited by the child process.
Linux uses the pthread library call pthread_create() to spawn a thread:
|
Note: In Windows, the number of threads a process can create is limited by the available virtual memory. By default, every thread has one megabyte of stack space. Therefore, you can create at most 2,028 threads. If you reduce the default stack size, you can create more threads. In Linux, the maximum number of process per user can be found using ULIMIT -a (limits for all users), and you can update it by using ULIMIT -u, but it would be valid only for that logon. The header files under /usr/Include/limit.h and ulimit.h define these constants. You can modify them and recompile kernel to hv permanent effect. For POSIX threadlimits, the THREAD_THREADS_MAX macro defines the maximum limit and is defined in local_lim.h.
Specifying the thread function
The parameter lpStartAddress in the CreateThread() is the address of the function that the newly created thread will execute.
The parameter start_address for the Linux library call pthread_create() is the address of the function that the newly created thread will execute.
Parameter passing to the thread function
In Windows, the parameter lpParameter for the system call CreateThread() specifies the parameter to be passed to the newly created thread. It specifies the address of the data item to be passed to the new thread.
In Linux, the parameter arg for the library call pthread_create() specifies the parameter to be passed to the new thread.
Setting the stack size
In Windows, the parameter dwStackSize for the CreateThread() is the size of stack in bytes that is to be allocated for the new thread. The stack size should be a non-zero multiple of 4 KB and a minimum of 8 KB.
In Linux, the stack size is set in the pthread attributes object; that is, the parameter threadAttr of type pthread_attr_t is passed to the library call pthread_create(). This object needs to be initialized by the call pthread_attr_init() before any attributes are set. The attribute object is destroyed using the call pthread_attr_destroy():
|
Note that all of the pthread_attr_setxxxx calls achieve similar functionality to the pthread_xxxx calls (if available) except that you can use pthread_attr_xxxx only before thread creation to update the attribute object that will be passed as a parameter to pthread_create. Meanwhile, you can use pthread_xxxx calls at any time after the thread has been created.
The stack size is set using the call pthread_attr_setstacksize(): int pthread_attr_setstacksize(pthread_attr_t *threadAttr, int stack_size);.
Exiting a thread
In Windows, the system call ExitThread() terminates the thread. The dwExitCode is the return value of the thread, and it can be retrieved from another thread by calling GetExitCodeThread().
|
The Linux equivalent for this is the library call pthread_exit(). The retval is the return value of the thread, and you can retrieve it from another thread by calling pthread_join(): int pthread_exit(void* retval);.
Thread states
In Windows, there are no explicit thread states maintained with respect to thread termination. However, WaitForSingleObject() allows a thread to wait explicitly on the termination of a specific or non-specific thread within the process.
In Linux, threads are by default created in joinable state. In joinable state, another thread can synchronize on the thread's termination and recover its termination code using the function pthread_join(). The thread resources of the joinable thread are released only after it is joined.
Windows uses WaitForSingleObject() to wait for a thread to terminate:
|
Where:
hHandleis the pointer to the thread handle.dwMillisecondsis the time out value in milliseconds. If the value is set to INFINITE, then it blocks the calling thread/process indefinitely.
Linux uses pthread_join() to do the same: int pthread_join(pthread_t *thread, void **thread_return);.
In the detached state, the thread resources are immediately freed when it terminates. The detached state can be set by calling pthread_attr_setdetachstate() on the thread attribute object: int pthread_attr_setdetachstate (pthread_attr_t *attr, int detachstate);. A thread created in a joinable state can later be put into a detached state using the pthread_detach() call: int pthread_detach (pthread_t id);.
Changing priority
In Windows, the priority of the thread is determined by the priority class of its process and the priority level of the thread within the priority class of the process. In Linux, the thread itself is the unit of execution and has its own priority. It has no dependency on the priority of its process.
In Windows, you can use SetPriorityClass() to set the priority class for the specified process:
|
dwPriorityClass is the priority class of the process, and it is set to any of the following values:
IDLE_PRIORITY_CLASSBELOW_NORMAL_PRIORITY_CLASSNORMAL_PRIORITY_CLASSABOVE_NORMAL_PRIORITY_CLASSHIGH_PRIORITY_CLASSREALTIME_PRIORITY_CLASS
Once the priority class of the process is set, SetThreadPriority() is used to set the priority level of the thread within the priority class of the process:
|
nPriority is the priority value of the thread, and it is set to one of the following values:
THREAD_PRIORITY_ABOVE_NORMALsets the priority to 1 point above the priority class.THREAD_PRIORITY_BELOW_NORMALsets the priority to 1 point below the priority class.THREAD_PRIORITY_HIGHESTsets the priority to 2 points above the priority class.THREAD_PRIORITY_IDLEsets base priority to 1 forIDLE_PRIORITY_CLASS,BELOW_NORMAL_PRIORITY_CLASS,NORMAL_PRIORITY_CLASS,ABOVE_NORMAL_PRIORITY_CLASS, orHIGH_PRIORITY_CLASSprocesses, and sets base priority to 16 forREALTIME_PRIORITY_CLASSprocesses.THREAD_PRIORITY_LOWESTsets the priority to 2 points below the priority class.THREAD_PRIORITY_NORMALsets to normal priority for the priority class.THREAD_PRIORITY_TIME_CRITICALsets the base priority to 15 forIDLE_PRIORITY_CLASS,BELOW_NORMAL_PRIORITY_CLASS,NORMAL_PRIORITY_CLASS,ABOVE_NORMAL_PRIORITY_CLASS, orHIGH_PRIORITY_CLASSprocesses, and sets base priority to 31 forREALTIME_PRIORITY_CLASS.
Tutorial Pages:
» A mapping guide for complex, multithreaded, multiprocess applications
» Processes
» Creating a process
» Terminating a process
» Using wait functions
» Exiting a process
» Environment variables
» Examples
» Threads
» Examples of processes and threads
» Next in the series
» Resources
First published by IBM DeveloperWorks
| Related Tutorials: » How to Install PHP 5 on Linux » How to Install Apache 2 on Linux » How to Install MySQL 5.0 on Linux » SMB Caching » Mound --Bind » Tar Wild Card Interpretation |
