在Linux中进程和线程之间的区别 [英] Distinction between processes and threads in Linux

查看:147
本文介绍了在Linux中进程和线程之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由罗伯特·爱这个答案和Linux内核开发 ,随后在的clone()系统调用,我发现,在Linux的进程和线程(几乎)没有区别内核。它们之间有一些调整(为更多的共享或少共享的报价SO问题讨论),但我仍然有一些问题有待回答。

After reading up on this answer and "Linux Kernel Development" by Robert Love and, subsequently, on the clone() system call, I discovered that processes and threads in Linux are (almost) indistinguishable to the kernel. There are a few tweaks between them (discussed as being "more sharing" or "less sharing" in the quoted SO question), but I do still have some questions yet to be answered.

最近,我的工作就涉及了几个POSIX线程的程序,并决定尝试这个premise。在创建两个线程的过程,当然,所有的线程获得通过 pthread_self()然而的,而不是由<$ C $返回的唯一值C> GETPID()。

I recently worked on a program involving a couple of POSIX threads and decided to experiment on this premise. On a process that creates two threads, all threads of course get a unique value returned by pthread_self(), however, not by getpid().

我创建了一个示例程序如下:

A sample program I created follows:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <pthread.h>

void* threadMethod(void* arg)
{
    int intArg = (int) *((int*) arg);

    int32_t pid = getpid();
    uint64_t pti = pthread_self();

    printf("[Thread %d] getpid() = %d\n", intArg, pid);
    printf("[Thread %d] pthread_self() = %lu\n", intArg, pti);
}

int main()
{
    pthread_t threads[2];

    int thread1 = 1;

    if ((pthread_create(&threads[0], NULL, threadMethod, (void*) &thread1))
         != 0)
    {
        fprintf(stderr, "pthread_create: error\n");
        exit(EXIT_FAILURE);
    }

    int thread2 = 2;

    if ((pthread_create(&threads[1], NULL, threadMethod, (void*) &thread2))
         != 0)
    {
        fprintf(stderr, "pthread_create: error\n");
        exit(EXIT_FAILURE);
    }

    int32_t pid = getpid();
    uint64_t pti = pthread_self();

    printf("[Process] getpid() = %d\n", pid);
    printf("[Process] pthread_self() = %lu\n", pti);

    if ((pthread_join(threads[0], NULL)) != 0)
    {
        fprintf(stderr, "Could not join thread 1\n");
        exit(EXIT_FAILURE);
    }

    if ((pthread_join(threads[1], NULL)) != 0)
    {
        fprintf(stderr, "Could not join thread 2\n");
        exit(EXIT_FAILURE);
    }

    return 0;
}

(这是编译在64位的Fedora;由于用于的pthread_t 64位类型从&LT来源;比特/ pthreadtypes。 H&GT; 中,code将需要小的改动编译在32位版本)

(This was compiled on 64-bit Fedora; due to the 64-bit types used for pthread_t sourced from <bits/pthreadtypes.h>, the code will require minor changes to compile on 32-bit editions.)

我得到的输出如下:

[bean@fedora ~]$ ./thread_test 
[Process] getpid() = 28549
[Process] pthread_self() = 140050170017568
[Thread 2] getpid() = 28549
[Thread 2] pthread_self() = 140050161620736
[Thread 1] getpid() = 28549
[Thread 1] pthread_self() = 140050170013440
[bean@fedora ~]$ 

使用调度锁定在 GDB ,我可以保持程序和它的线程活着,所以我可以捕捉到哪些表示,其中的只是显示进程的是:

By using scheduler locking in gdb, I can keep the program and its threads alive so I can capture what top says, which, just showing processes, is:

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
28602 bean      20   0 15272 1112  820 R  0.4  0.0   0:00.63 top
 2036 bean      20   0  108m 1868 1412 S  0.0  0.0   0:00.11 bash
28547 bean      20   0  231m  16m 7676 S  0.0  0.4   0:01.56 gdb
28549 bean      20   0 22688  340  248 t  0.0  0.0   0:00.26 thread_test
28561 bean      20   0  107m 1712 1356 S  0.0  0.0   0:00.07 bash

和显示线程时,他说:

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
28617 bean      20   0 15272 1116  820 R 47.2  0.0   0:00.08 top
 2036 bean      20   0  108m 1868 1412 S  0.0  0.0   0:00.11 bash
28547 bean      20   0  231m  16m 7676 S  0.0  0.4   0:01.56 gdb
28549 bean      20   0 22688  340  248 t  0.0  0.0   0:00.26 thread_test
28552 bean      20   0 22688  340  248 t  0.0  0.0   0:00.00 thread_test
28553 bean      20   0 22688  340  248 t  0.0  0.0   0:00.00 thread_test
28561 bean      20   0  107m 1860 1432 S  0.0  0.0   0:00.08 bash

这似乎是相当清楚的程序,或者内核,具有在相反过程限定线程的不同方式。为什么?

It seems to be quite clear that programs, or perhaps the kernel, have a distinct way of defining threads in contrast to processes. Each thread has its own PID according to top - why?

推荐答案

这混乱从内核开发原持有的非理性和错误的观点,即线程可以几乎完全在用户空间使用内核进程作为原始实施的其实都是干只要内核提供了一个方法,使他们共享内存和文件描述符。这导致了臭名昭著的坏LinuxThreads实现POSIX线程的,这是相当错误的名称,因为它没有给任何远程类似POSIX线程的语义。最终LinuxThreads中被替换(由NPTL),但很多混乱的术语和误解仍然存在。

These confusions all stem from the fact that the kernel developers originally held an irrational and wrong view that threads could be implemented almost entirely in userspace using kernel processes as the primitive, as long as the kernel offered a way to make them share memory and file descriptors. This lead to the notoriously bad LinuxThreads implementation of POSIX threads, which was rather a misnomer because it did not give anything remotely resembling POSIX thread semantics. Eventually LinuxThreads was replaced (by NPTL), but a lot of the confusing terminology and misunderstandings persist.

要实现的第一个也是最重要的一点是,PID是指在内核空间和用户空间不同的事情。内核调用什么的PID实际上是内核级的线程ID(通常称为的TID),不要与的pthread_t 混淆这是一个独立的标识符。系统上的每个螺纹,无论是在相同的工艺或不同的一个,具有独特的TID(或「PID」在内核的术语)。

The first and most important thing to realize is that "PID" means different things in kernel space and user space. What the kernel calls PIDs are actually kernel-level thread ids (often called TIDs), not to be confused with pthread_t which is a separate identifier. Each thread on the system, whether in the same process or a different one, has a unique TID (or "PID" in the kernel's terminology).

什么视为一个PID中的处理的POSIX感,另一方面,被称为在内核一个线程组ID或TGID。每个进程包括一个或多​​个线程(内核进程)每个都有自己的TID(内核的PID),但所有的共享相同TGID,这是在其中主运行。

What's considered a PID in the POSIX sense of "process", on the other hand, is called a "thread group ID" or "TGID" in the kernel. Each process consists of one or more threads (kernel processes) each with their own TID (kernel PID), but all sharing the same TGID, which is equal to the TID (kernel PID) of the initial thread in which main runs.

显示你的线程,它显示的TID(内核的PID),没有的PID(内核TGIDs),这就是为什么每个线程都有一个独立的。

When top shows you threads, it's showing TIDs (kernel PIDs), not PIDs (kernel TGIDs), and this is why each thread has a separate one.

通过NPTL的到来,大多数系统调用,拿上调用的处理的被改变对待PID为TGID和行为整个线程组上(POSIX一个PID参数或行为过程)。

With the advent of NPTL, most system calls that take a PID argument or act on the calling process were changed to treat the PID as a TGID and act on the whole "thread group" (POSIX process).

这篇关于在Linux中进程和线程之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆