Subj : Re: Threads and processes on Linux To : comp.programming.threads,comp.os.linux.misc,comp.sources.d From : doug Date : Thu Mar 31 2005 11:10 pm wrote in message news:1112273796.254309.214020@z14g2000cwz.googlegroups.com... > Hello Gus, > >> I have often heard that in a Linux environment there is no difference >> between threads and processes. I want to know if that is merely >> "rhetoric" or if that is really so. > > It is more than "rhetoric". From a scheduler perspective, threads and > processes are the same entity. > > Actually, Linux views a thread as a process with some special > properties: it shares with its 'parent task' (the spawning thread) the > things that are needed to make it to *behave like* a thread. Namely, > > (o) memory descriptors and all Page tables. This means that the child > task runs in the same memory space as the parent task. All memory > mappings or write operations are visible in both entities. > > (o) file system information (root directory, current directory and > umask). > > (o) open files > > (o) signal handlers. > > The fact that threads were modelled as processes is visible when using > LinuxThreads and/or older 2.4.x kernel. For instance, each spawned > thread has a different pid, and are children of the so-called manager > thread. > > With the advent of NPTL and 2.6.x kernel, a process *appears* as a > collection of thread, where threads are peers. But it is an > _abstraction_ provided by NPTL: for instance, a sibling relationship > between threads still exists, but is now hidden to you. Inside the > kernel, threads and processes are similar entities (the scheduler won't > even bother to make any distinction). > > >> For example, I have seen that getpid() in all threads returns the > same value >> (as I think it should). > > Only with NPTL. > > >> This means from the perspective of operations associated with > processes >> (ps, signal etc.), all the threads are viewed as a single entity. > > Yes, because NPTL provides an abstraction that let you think it is so. > But, in reality, the threads of a process are different entities. > > >> Also, if the spawning thread terminates (e.g. it does not do a join > on >> the spawned thread), the spwaned thread also seems to terminate. In >> other words, the lifetime of a spawned thread does not seem to exceed >> the lifetime of the spawning thread. > > Generally speaking, this is not correct. You can perfectly create a > thread that lasts more than the spawner thread. Consider for instance > the following simple program: > > #include > #include > #include > > void* > my_thread(void* ignore) > { > int i; > > for (i=5; i>=1; i--) { > printf ("%d...", i); fflush(stdout); > sleep(1); > } > printf ("0\nCiao!\n"); > return NULL; > } > > int > main() > { > pthread_t tid; > > pthread_create (&tid, NULL, my_thread, NULL); > printf ("Main terminate\n"); > pthread_exit (NULL); > printf ("Never reached!\n"); > return 0; > } > > If you comment the pthread_exit(NULL) out in the main(), then you get > the behavior that you have described. However, it is not a general > rule, but a particular behavior of the main() thread: when main() > returns, all threads in the process go away. That's because of how the > C language defines main(), more than anything else. It's simplest to > imagine that the environment calls main like this: > > exit(main(argc, argv, envp)); > > So that when main() returns, that return value is passed to exit(), > which tears down the process, and all threads therein. > > >> So what exactly are we saying when we state that "there is no >> difference between threads and processes on Linux"? > > I Hope, things got clearer now. > > > Cheers, > Loic. > Loic, Thanks for the post - very helpful - it clears a few things up for me! I'm going to be cheeky and ask you a question that I posted below about a multithreaded bit of code I'm writing. Just incase you didn't see it :) I've got a 2.4 kernel with linuxthreads, and an app with about 300 threads doing network I/O in 20 millisecond bursts. On a single CPU box, this is fine. On an SMP box, performance drops through the floor. There are no data pages shared between threads. vmstat, etc. show the processors 60% idle. My theory is that each thread is being repeatedly scheduled on a different CPU, and so a lot of time is being spent loading the memory accessed by the thread into the CPU cache, and then (once it's dirtied) invalidating the cache entries on the last processor to host it. Am I in the right ballpark? Even playing the right sport? I hacked a box so it would run the thread affinity stuff added to the 2.5.8 kernel, but i'm not sure of my success. Binding each thread to a particular CPU made no difference. Binding them all to a single CPU (id 0) made a *huge* difference, but it still wasn't as good as uniprocessor. I only got thread affinity - I didn't get interrupt affinity. My next theory is interrupts. The 2.4 kernel round-robins responsibility for handling interrupts around the cpus - each receives them for a short period. Each I/O operation generates an interrupt. If it's not delivered to the correct processor (75% chance), time is wasted transmitting the information between the cpu receiving the interrupt and the cpu running the thread. Ok - what sport am I playing now? Phew. That's a lot of gumph. Upshot: - are my theories anywhere correct? And if not, what could be causing the performance drop on SMP? (I realise this is impossible to answer! But there's no data sharing, all objects and per-thread memory accesses lie on per-thread memory pages, there's no swapping going on, all data is resident in main memory, processors are barely sweating, aaarrggh!) - are there any reliable interrupt/thread affinity patches for 2.4 (being lazy here - I will try to find out myself) - is this function available in 2.6 and/or NTPL? (ditto) Thanks for all the useful info in the post. Doug .