LINUX.ORG.RU

Си. ps -a


0

1

Суть задачи:
Мне нужно узнать выводит ли конкретная программа в конкретный терминал.
В консоли я могу решить подобную задачу так:
«ps -a | grep <program_name>»
Но мне надо получить этот результат в сишном коде.
Я, конечно, могу добиться результата через popen, но это будет означать, что мне придётся каждый квант времени дёргать этот несчастный popen чуть менее раз, чем дофига.
Придумал посмотреть в исходники ps, но мозг зафейлился при чтении такого кода.
Кто-то в курсе в какую сторону надо копать?

★★☆
Ответ на: комментарий от Stahl

Например, информация о процессах? Я даже не знаю. А что тебе нужно?

Подавляющее большинство утилит для работы с процессами пользуют именно /proc.

schizoid ★★★
()
Последнее исправление: schizoid (всего исправлений: 1)
vadim@aquila:~$ ldd `which ps `
	linux-gate.so.1 (0xb7720000)
	libprocps.so.1 => /usr/lib/libprocps.so.1 (0xb76c7000)
	libc.so.6 => /usr/lib/libc.so.6 (0xb7519000)
	libdl.so.2 => /usr/lib/libdl.so.2 (0xb7514000)
	/lib/ld-linux.so.2 (0xb7721000)
vadim@aquila:~$ pacman -Qo /usr/lib/libprocps.so.1
/usr/lib/libprocps.so.1 принадлежит procps-ng 3.3.8-1
vadim@aquila:~$ pacman -Ql procps-ng | grep include
procps-ng /usr/include/
procps-ng /usr/include/proc/
procps-ng /usr/include/proc/alloc.h
procps-ng /usr/include/proc/devname.h
procps-ng /usr/include/proc/escape.h
procps-ng /usr/include/proc/procps.h
procps-ng /usr/include/proc/pwcache.h
procps-ng /usr/include/proc/readproc.h
procps-ng /usr/include/proc/sig.h
procps-ng /usr/include/proc/slab.h
procps-ng /usr/include/proc/sysinfo.h
procps-ng /usr/include/proc/version.h
procps-ng /usr/include/proc/wchan.h
procps-ng /usr/include/proc/whattime.h
vadim@aquila:~$ 

Ну ты понял, да?

geekless ★★
()
Ответ на: комментарий от schizoid

А что тебе нужно?

Мне нужно узнать выводит ли конкретная программа в конкретный терминал. Определять хочу по названию программы.

Переходи на каноничную black тему оформления. Тут не только заголовки, но и тело сообщения можно прочитать:)

Stahl ★★☆
() автор топика
Ответ на: комментарий от madcore

Не портабельно.

Боюсь, что мой код уже кроме как из-под линукса работать нигде не будет. Так что это не так уж и страшно.

Stahl ★★☆
() автор топика
Ответ на: комментарий от Stahl

Мне нужно узнать выводит ли конкретная программа в конкретный терминал.

Каждый процесс ассоциирован с терминалом. Если процесс ассоциирован с «твоим» терминалом, значит он в него выводит.

geekless ★★
()
Ответ на: комментарий от geekless

У меня обратная задача. Есть терминал и надо узнать какие процессы с ним ассоциированы.

Stahl ★★☆
() автор топика
Ответ на: комментарий от Stahl

У меня обратная задача. Есть терминал и надо узнать какие процессы с ним ассоциированы.

Шарик, ты балбес.

Задача та же самая. Берешь список процессов в системе и смотришь, какие из них выводят на твой терминал.

libprocps.so тебе в помощь.

geekless ★★
()
Ответ на: комментарий от schizoid

Не-не-не...
Мне нужен список программ, выводящих в данный конкретный терминал.
Не буду же я парсить все программы в поисках нужного мне терминала?

Stahl ★★☆
() автор топика

:)

.....

char ch;
system("ps -a | grep program_name > /tmp/123456789987456321");
FILE *my_file=fopen("/tmp/123456789987456321","r");

while((ch=getc(my_file))!='\0')
{
   printf("%c",ch);
   
   .....
};

fclose(my_file);

Dron ★★★★★
()
Последнее исправление: Dron (всего исправлений: 1)
Ответ на: комментарий от Stahl

Не буду же я парсить все программы в поисках нужного мне терминала?

Куда ты с подводной лодки денешься :)

anonymous
()

ps -a | grep <program_name>

Научись читать мануал:

ps -C <program_name>


Или ты не знаешь, что такое $0 ?

Плюс один к решению читать /proc, но и еще вдобавок для совместимости неплохо читать и /sys. Далее изучаешь http://man7.org/linux/man-pages/man5/proc.5.html и понимаешь, что твою задачу это не решает. Чтобы понять выводит ли программа что-то в консоль/терминал надо распознавать вдобавок и какие FD открыты. Может файл, может сокет, может еще до кучи всего - закрыли STDIN, закрыли STDERR, или вообще все закрыли и все переоткрыли, но под другими номерами, не 0,1,2 - что конечно признак особого мышления :)

gh0stwizard ★★★★★
()

А почему бы не дергать саму ps через системные вызовы fork() и execve()? На худой конец, можно использовать system().

happycorsair
()
Ответ на: комментарий от happycorsair

дергать саму ps

Думаю это самый простой способ.
Беда в том, что мне очень часто надо будет это делать.
Конечно надо сначала попробовать, а потом уже смотреть будет ли это поблемой, но руки же чешутся заняться преждевременной оптимизацией:)

Stahl ★★☆
() автор топика
Ответ на: комментарий от madcore

Чем не портабельно? Ну где то путь поменять, где то пропарсить по другому и всё.

Dron ★★★★★
()
Ответ на: комментарий от Stahl

Беда в том, что мне очень часто надо будет это делать.

Тебе в третий раз на libprocps.so указать?

geekless ★★
()
Ответ на: комментарий от geekless

Каждый процесс ассоциирован с терминалом. Если процесс ассоциирован с «твоим» терминалом, значит он в него выводит.

Все-таки не каждый процесс имеет ассоциации с терминалом)

happycorsair
()
Ответ на: комментарий от happycorsair

Все-таки не каждый процесс имеет ассоциации с терминалом)

В рамках задачи, решаемой ТСом, этого достаточно. Выводить на терминал, но при этом не быть связанным с ним — это случай, когда программе файл терминала специально подсунут в качестве stdout или в параметрах запуска. А раз пользователь это специально делает, ему виднее.

Ну и разумеется есть еще удаленный доступ, но тут уж ничего не сделаешь.

geekless ★★
()

если только Linux, то:

$ ls -l /proc/4818/fd/0
lr-x------ 1 rymis rymis 64 июн 17 15:07 /proc/4818/fd/0 -> /dev/pts/1
$ readlink /proc/4818/fd/0
/dev/pts/1

Как-то так.

rymis ★★
()

А вроде еще есть вариант. Узнаешь через tcgetsid() id текущей сессии. А потом у нужных тебе процессов проверяешь через getsid() id их сессии. Получается, что больше ничего не надо)))

happycorsair
()
Ответ на: комментарий от Stahl

Вообще-то тебе нужен не ps, а lsof.
Но он точно так же сканирует /proc, обшаривая
/proc/PID/(fd|fdinfo), /proc/PID/(cmdline|comm|exe).

ABW ★★★★★
()

я бы постарался придумать что-нить на systemtap/whatever или же подхачил драйвер терминала.

true_admin ★★★★★
()
Ответ на: комментарий от gh0stwizard

Далее изучаешь http://man7.org/linux/man-pages/man5/proc.5.html17 и понимаешь, что твою задачу это не решает. Чтобы понять выводит ли программа что-то в консоль/терминал надо распознавать вдобавок и какие FD открыты.

В /proc/PID/stat есть tty_nr. У каждого процесса есть терминал, с котором он ассоциирован.

Согласен, процесс может взять и открыть любой терминал и писать в него, но это редкий случай и это будет неполноценная работа с терминалом, например, не будет доставляться SIGINT по ^C. С таким поведением вспоминается только команда write().

Так что ИМХО достаточно искать по управляющему терминалу.

gv
()
Ответ на: комментарий от happycorsair

Узнаешь через tcgetsid() id текущей сессии. А потом у нужных тебе процессов проверяешь через getsid() id их сессии.

Гм, AFAIK нет гарантий, что у процессов с разными сессиями разные терминалы, а с одной и той же сессией — один и тот же терминал.

$ echo -n session:; cat /proc/self/stat | cut -d" " -f6; echo -n tty:; tty
session:31066
tty:/dev/pts/4

$ setsid sh -c 'echo -n session:; cat /proc/self/stat | cut -d" " -f6; echo -n tty:; tty'
session:344 
tty:/dev/pts/4
gv
()
Ответ на: комментарий от gv

AFAIK нет гарантий, что у процессов [...] с одной и той же сессией — один и тот же терминал.

Точно, поменять моожно с помощью ioctl(TIOCSCTTY).

gv
()

Мне нужно узнать выводит ли конкретная программа в конкретный терминал.

Если решать задачу в общем случае, то я бы перебирал нужные процессы в proc и проверял их controlling tty.

На заметку: еще есть функция tcgetpgrp(), которая возвращает foreground-группу процессов для терминала.

Например, если запустить команду так:

$ ls

она будет в этой foreground-группе, а так не будет:

$ ls &

gv
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.