Как я могу просмотреть потоки для выполняемого процесса, который создает потоки?

Вопрос или проблема

Я написал очень небольшую программу, которая создает два потока:

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

void *start()
{
        printf("Я новый поток!\n");
        printf("%d\n",pthread_self());
}

void main()
{

        pthread_t thread_id1;
        pthread_t thread_id2;

        pthread_create(&thread_id1,NULL,start,NULL);
        pthread_create(&thread_id2,NULL,start,NULL);
        //pthread_join(thread_id,NULL);
        sleep(30);

}

Когда я компилирую и запускаю программу с:

gcc create.c -lpthread
./a.out

И открываю новый терминал и пытаюсь просмотреть потоки, вот что я получаю:

ps -efL | grep a.out
root      1943 20158  1943  0    1 15:25 pts/4    00:00:00 ./a.out
root      1985  1889  1985  0    1 15:25 pts/5    00:00:00 grep --color=auto a.out

Так почему я не вижу здесь два идентификатора потоков?

Два дополнительных потока пишут свое сообщение и завершаются, поэтому у вас нет времени увидеть их с помощью ps.

из man pthread_create:

Новый поток завершается одним из следующих способов:

*
Он вызывает pthread_exit(3), указывая значение статуса выхода, доступное другому потоку в том же процессе, который вызывает
pthread_join(3).

*
Он возвращается из start_routine(). Это эквивалентно вызову pthread_exit(3) с значением, указанным в операторе return.

[…]

Вы можете отслеживать, что происходит, например, с помощью strace:

$ strace -f -e trace=clone,exit ./a.out 
clone(strace: процесс 409 подключен
child_stack=0x7f7126930ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f71269319d0, tls=0x7f7126931700, child_tidptr=0x7f71269319d0) = 409
[pid   408] clone(strace: процесс 410 подключен
child_stack=0x7f712612fff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f71261309d0, tls=0x7f7126130700, child_tidptr=0x7f71261309d0) = 410
Я новый поток!
Я новый поток!
647173888
638781184
[pid   409] exit(0 <незавершенный ...>
[pid   410] exit(0 <незавершенный ...>
[pid   409] <... выход возобновлен>) = ?
[pid   410] <... выход возобновлен>) = ?
[pid   410] +++ завершен с кодом 0 +++
[pid   409] +++ завершен с кодом 0 +++

Ответ или решение

Для того чтобы просмотреть потоки (threads) запущенного процесса, который создает дополнительные потоки, вам потребуются более специальные инструменты, чем просто команда ps. Ниже подробно описано, как это сделать с использованием различных методов.

1. Изменение кода

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

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

void *start(void *arg) {
    printf("Я новый поток! ID потока: %lu\n", pthread_self());
    return NULL;
}

int main() {
    pthread_t thread_id1;
    pthread_t thread_id2;

    pthread_create(&thread_id1, NULL, start, NULL);
    pthread_create(&thread_id2, NULL, start, NULL);

    // Ожидание завершения дочерних потоков
    pthread_join(thread_id1, NULL);
    pthread_join(thread_id2, NULL);

    return 0;
}

2. Просмотр потоков с помощью ps

После добавления pthread_join, вы можете запустить вашу программу и затем открыть новую терминальную сессию для выполнения команды:

ps -efL | grep a.out

Теперь вы должны увидеть два дополнительных потока, которые отвечают каждому из созданных вами потоков.

3. Использование инструмента top

Вы также можете использовать команду top для просмотра всех потоков в процессе. Запустите top и затем нажмите H для переключения на режим просмотра потоков. В данном режиме вы сможете увидеть, как потоки вашего процесса создаются и завершаются в реальном времени.

4. Использование htop

htop является более современным и удобным вариантом по сравнению с top. Убедитесь, что он установлен, а затем запустите его:

htop

Нажмите F5, чтобы переключиться на древовидный вид, что облегчает просмотр потоков, созданных вашим процессом.

5. Анализ с помощью strace

Если вам нужно отследить системные вызовы создания потоков, вы можете воспользоваться strace:

strace -f -e trace=clone,exit ./a.out

Это позволит вам наблюдать за созданием потоков и их завершением, а также за другими вызовами. Вы сможете увидеть информацию о clone и exit, что поможет в диагностике состояния потоков.

6. Использование gdb

Если вам требуется мышление с дебаггингом, gdb предоставляет мощные инструменты. Запустите вашу программу через gdb:

gdb ./a.out

Затем используйте команды для вывода информации о потоках:

(gdb) run
(gdb) info threads

Заключение

Существует несколько способов мониторить создаваемые потоки в вашем приложении на C, каждый из которых имеет свои преимущества. Изменение вашего кода для корректного ожидания завершения потоков вместе с использованием инструментов командной строки, таких как ps, top, htop, и strace, предоставляют мощные возможности для отладки и мониторинга.

Оцените материал
Добавить комментарий

Капча загружается...