Nano Hash - криптовалюты, майнинг, программирование

Как создание потока влияет на идентификатор процесса

У меня есть следующий код:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/wait.h>
#define CHILD_NO 2
#define THREAD_NO 2
int counter = 0;
void *func(void *thread_no) {
    counter = counter + 1;
    printf("Func:  Proces ID = %d Parent process ID = %d Thread no = %d, Counter = %d \n", getpid(), getppid(), thread_no, counter);
    pthread_exit(NULL);
}

int main(void) {
    pthread_t threads[THREAD_NO];
    int childs[CHILD_NO];
    int rc, i, j;
    int f = 1;
    printf("Main: Proces ID = %d Parent process ID: %d\n", getpid(), getppid());
    for (i = 0; i < CHILD_NO; i++) {
        if (f > 0)
            f = fork();
        if (f == 0)
            break;
        else
            childs[i] = f;
    }
    if (f == 0) {
        printf("Child: Proces ID: %d Parent process ID: %d counter:%d\n" , getpid(), getppid(), counter);
        /*for(j = 0; j < THREAD_NO; j++)
            rc = pthread_create(&threads[j], NULL, func, (void *)j);*/
    }
    else{
        for (i = 0; i < CHILD_NO; i++)
            printf("Main: Child[%d] ID: %d created.\n", i, childs[i]);
        wait(NULL);
    }
    pthread_exit(0);
    return 0;
}

Если я запускаю его с закомментированной частью потока, я получаю следующий вывод:

Main: Proces ID = 31138 Parent process ID: 28446
Child: Proces ID: 31139 Parent process ID: 31138 counter:0
Child: Proces ID: 31140 Parent process ID: 31138 counter:0
Main: Child[0] ID: 31139 created.
Main: Child[1] ID: 31140 created.

Что ожидается. Родитель вызывает fork, дочерний процесс нажимает break и выходит из цикла. Это происходит 2 раза. Итак, у нас есть родительский процесс с двумя дочерними процессами. Это все. Таким образом, если у родительского процесса есть PID, у дочернего процесса будет PID+1, а у другого — PID+2.

Если я удалю комментарии и запущу код, я получу следующее:

Main: Proces ID = 31664 Parent process ID: 28446
Child: Proces ID: 31665 Parent process ID: 31664 counter:0
Child: Proces ID: 31668 Parent process ID: 31664 counter:0
Main: Child[0] ID: 31665 created.
Main: Child[1] ID: 31668 created.
Func:  Proces ID = 31665 Parent process ID = 31664 Thread no = 1, Counter = 1 
Func:  Proces ID = 31665 Parent process ID = 31664 Thread no = 0, Counter = 2 
Func:  Proces ID = 31668 Parent process ID = 31664 Thread no = 1, Counter = 1 
Func:  Proces ID = 31668 Parent process ID = 31664 Thread no = 0, Counter = 2 

Теперь я понимаю, как ведут себя потоки. Меня смущают не их выходы.

Как и почему PID дочерних процессов отличаются на 3? Разве древовидная иерархия процессов не должна оставаться прежней?


  • В Linux нет реальной разницы между потоком и процессом, оба (в конечном счете) создаются с использованием clone системный вызов. 03.04.2015
  • @JoachimPileborg Итак, я предполагаю, что это работает следующим образом: Main создает первый дочерний процесс (PID + 1), затем вызывает 2 потока (PID + 2, PID + 3), затем возвращается к основному и создает другой дочерний процесс (PID + 4) . 03.04.2015
  • @JoachimPileborg Тем не менее, дерево процессов остается прежним, верно? 03.04.2015
  • В основном да, но вы не гарантируете, что получите последовательные значения pid, так как вы можете быть упреждены, а другой процесс может создать новые процессы/потоки между ними. И да, дерево процессов будет таким же. 03.04.2015
  • Да, я пытался понять этот конкретный вывод. 03.04.2015
  • @JoachimPileborg: Между потоками и процессами существуют очень большие различия. Ваша информация устарела. Было бы правильно сказать, что идентификаторы потоков и идентификаторы процессов существуют в одном и том же (числовом) пространстве имен. Но они разные. 03.04.2015
  • Вот ответ, который я написал по теме: stackoverflow.com/questions/9154671/ 03.04.2015
  • @R.. в ядре Linux нет потоков и процессов. Оба представлены одной и той же структурой task_struct. Единственное отличие состоит в том, что потоки, принадлежащие одному и тому же процессу, совместно используют некоторые ресурсы, которые зависят от системного вызова clone(2). Но в обычном случае (например, с потоками posix) они совместно используют отображение памяти, файловые дескрипторы и многое другое. 03.04.2015
  • @holgac: Да, есть. Процесс — это то, что ядро ​​называет группой потоков, и он состоит из всех задач (потоков), совместно использующих один и тот же tgid. 03.04.2015

Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..