Главная страница


ru.unix.bsd

 
 - RU.UNIX.BSD ------------------------------------------------------------------
 From : Vadim Kolontsov                      2:5020/400     27 Apr 2000  15:50:40
 To : Yury Lazarev
 Subject : Re: Получить список процессов из C
 -------------------------------------------------------------------------------- 
 
 In article <gq4ggso087d7le5s4l931o80ahtmjt4v8d@4ax.com>, Yury Lazarev wrote:
 
 >Каким образом можно вытащить командную строку, с которой были запущены
 >процессы в Unix (наподобие того, что выдает команда ps).
 
   в новых unix'ах для этого используется псевдо-FS: /proc. Там все просто:
 cd /proc; ls -l; cd 3354; cat cmdline.. В Linux и PicoBSD, если мне память 
 не изменяет, 'ps' работает именно через /proc
 
   Традиционно же ps (и другие подобные вещи, скажем, netstat или top) 
 делается через kernel virtual memory interface (KVM). 
 
   kvm позволяет получить доступ к памяти ядра, погулять по внутренним 
 структурам (например, списку процессов). Интерфейс прост: kvm_open и
 kvm_openfiles (позволяющие открыть не только ядро в памяти, но и мертвое 
 ядро на диске); kvm_read, переносящая буфер произвольной длины из памяти 
 ядра ко мне в приложение; kvm_write, выполняющая обратные функции; 
 kvm_geterr (сообщение о произошедшей ошибке); kvm_close и прочее.
  
   В ядре много интересной информации. Hо как узнать смещения этих
 структур? С помощью kvm_nlist(3) (ее аналог для обычных файлов - nlist(3)).
 
   kvm_nlist позволяет получить адреса символических переменных. Используя
 эти адреса, мы считываем в нашу память содержимое областей памяти ядра. 
 Примерчик:
 
 ----------------------------------------------------------------------
 /* Как посмотреть load average на Solaris'е прямо в ядре */
 struct nlist nlst[] =
 {
   {"avenrun"},
   {0}
 };
 
 if (kvm_nlist(kd, nlst) == -1) {
   (сообщаем об ошибке; exit())
 }
 
 if (nlst->n_type == 0) {
   (сообщаем об ошибке; exit())
 }
 ----------------------------------------------------------------------
 
   После того, как адрес массива avenrun выяснен, мы можем прочитать его
 в память:
 
 ----------------------------------------------------------------------
   long avenrun[3];
 
   if (kvm_read(kd, nlst->n_value, (char *)avenrun, sizeof(avenrun)) == -1) {
     (сообщаем об ошибке; exit())
   }
 ----------------------------------------------------------------------
 
   FreeBSD несколько облегает работу с KVM/procs, вводя дополнительные
 функции: kvm_getprocs, kvm_getargv etc.
  
   Однако kvm_read() приходится использовать часто. Пусть мы хотим
 выяснить, какие сетевые соединений какими процессами используется. Пишем:
 
 ----------------------------------------------------------------------
   kp = kvm_getprocs(...KERN_PROC_ALL..., &cntproc);
 
   for( i = 0; i < cntproc; i++) {
      struct filedesc filedesc;
      struct file **files;
      struct file file;
      int fileslen;
 
      /* Список открытых файлов */
      kvm_read(kd, kp[c].kp_proc.p_fd, &filedesc, sizeof(filedesc) ..)
    
      fileslen = filedesc.fd_nfiles*sizeof(struct file *);
      files = malloc(fileslen);
 
      /* Загружаем массив указатель на fd'ы */
      kvm_read(kd, filedesc.fd_ofiles, files, fileslen);
 
      /* Пробегаем по файлам */
      for (j = 0; j < filedesc.fd_nfiles; j++, files++) {
 
       дальше загружаем структуру 'file' для каждого fd..
         kvm_read(kd, *files, &file, sizeof(struct file));
 
       выясняем тип fd:
         if (file.f_type = DTYPE_SOCKET) ...
 
          далее загружаем file.f_data как структуру socket,
          для определения socket family загружаем socket.so_proto (protosw),
          загружаем protosw.pr_domain и проверяем: domain.dom_faimyly == AF_INET
 
         sock.so_type == SOCK_DGRAM/SOCK_STREAM;
   
          далее загружаем protocol control block (pcb) - socket.so_pcb,
 
          и так далее, пока не выясним все, что нам интересно..
 
          довольно нудно, конечно; /proc - удобнее; но kvm дает доступ
          к чему угодно!
      }
   }
 ----------------------------------------------------------------------
 
   в 97-м году я кидал такую программку в freebsd-hackers как пример
 использования KVM. Пример вывода: 
 
 21319  tcp:ESTABLISHED     aa.bb.cc.dd:1339             aa.bb.dd.ee:119
 451    tcp:LISTEN          aa.bb.cc.dd:80               *:*
 6622   udp                 *:NNNN                       *:*
 
   и т.д...
 
 >Может быть кто-нибудь подскажет, как это проще сделать?
 
   kvm_getargv() возвращает массив (а-ля argv[]), в которым указаны
 параметры запуска (= командная строка). ps использует именно kvm_getargv().
 Можно извлечь те же данные и руками - через kvm_read() (см. описание
 структуры proc).
 
   char **a;
   a = kvm_getargv(...)
   if (a) while (*a) printf("%s ", *a++);
 
 >Пытался разобраться с исходниками ps - дохлый номер (маловато знаний).
 
   упорство и упорство - и все получится :)
 
 >В man как-то весьма невнятно описаны функции kvm. Где бы найти
 >какое-нибудь более подробное описание, желательно с примерами.
 
   4.4BSD Daemon Book, исходники ядра, исходные тексты программ...
 
 V.
 
 P.S. KVM в man pages описан нормально :)
 --- ifmail v.2.15dev5
  * Origin: Tver State University NOC (2:5020/400)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 Получить список процессов из C   Yury Lazarev   27 Apr 2000 14:18:49 
 Re: Получить список процессов из C   Vadim Kolontsov   27 Apr 2000 15:50:40 
Архивное /ru.unix.bsd/929531bbd771.html, оценка 2 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional