Linuxシステムで実行中のプロセスを一覧表示し、各プロセスが開いているファイルを一覧表示できるC/C++ APIが必要です。
not最終的に/ proc /ファイルシステムを直接読みたい。
誰もこれを行う方法を考えることができますか?
http://procps.sourceforge.net/
http://procps.cvs.sourceforge.net/viewvc/procps/procps/proc/readproc.c?view=markup
Psおよびその他のプロセスツールのソースです。彼らは確かにprocを使用します(おそらく従来の最善の方法であることを示しています)。そのソースは非常に読みやすいです。ファイル
/procps-3.2.8/proc/readproc.c
役に立つかもしれません。また、ephemientによる投稿として役立つ提案は、libprocによって提供されるAPIへのリンクです。ヘッダーとwhat-notの「-dev」バリエーション。
幸運
'/ procから読みたくない場合。次に、独自のシステムコールを実装するカーネルモジュールの作成を検討できます。また、次のような現在のプロセスのリストを取得できるように、システムコールを記述する必要があります。
/* ProcessList.c
Robert Love Chapter 3
*/
#include < linux/kernel.h >
#include < linux/sched.h >
#include < linux/module.h >
int init_module(void)
{
struct task_struct *task;
for_each_process(task)
{
printk("%s [%d]\n",task->comm , task->pid);
}
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Cleaning Up.\n");
}
上記のコードは http://linuxgazette.net/133/saha.html にある私の記事から引用したものです。独自のシステムコールを作成したら、ユーザースペースプログラムから呼び出すことができます。
どうぞ(C/C++):
ここで見つけることができました: http://ubuntuforums.org/showthread.php?t=657097
基本的に、/proc/<pid>
のすべての数値フォルダーをループし、/proc/<pid>/exe
でreadlinkを実行するか、コマンドライン引数cat /proc/<pid>/cmdline
が必要な場合
ちなみに、これはreadproc.c
が行うのと同じです(または少なくともやった)。
もちろん、うまくいけば、バッファオーバーフローの可能性なしにそれを実行できます。
#ifndef __cplusplus
#define _GNU_SOURCE
#endif
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h> // for opendir(), readdir(), closedir()
#include <sys/stat.h> // for stat()
#ifdef __cplusplus
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdarg>
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#endif
#define PROC_DIRECTORY "/proc/"
#define CASE_SENSITIVE 1
#define CASE_INSENSITIVE 0
#define EXACT_MATCH 1
#define INEXACT_MATCH 0
int IsNumeric(const char* ccharptr_CharacterList)
{
for ( ; *ccharptr_CharacterList; ccharptr_CharacterList++)
if (*ccharptr_CharacterList < '0' || *ccharptr_CharacterList > '9')
return 0; // false
return 1; // true
}
int strcmp_Wrapper(const char *s1, const char *s2, int intCaseSensitive)
{
if (intCaseSensitive)
return !strcmp(s1, s2);
else
return !strcasecmp(s1, s2);
}
int strstr_Wrapper(const char* haystack, const char* needle, int intCaseSensitive)
{
if (intCaseSensitive)
return (int) strstr(haystack, needle);
else
return (int) strcasestr(haystack, needle);
}
#ifdef __cplusplus
pid_t GetPIDbyName(const char* cchrptr_ProcessName, int intCaseSensitiveness, int intExactMatch)
#else
pid_t GetPIDbyName_implements(const char* cchrptr_ProcessName, int intCaseSensitiveness, int intExactMatch)
#endif
{
char chrarry_CommandLinePath[100] ;
char chrarry_NameOfProcess[300] ;
char* chrptr_StringToCompare = NULL ;
pid_t pid_ProcessIdentifier = (pid_t) -1 ;
struct dirent* de_DirEntity = NULL ;
DIR* dir_proc = NULL ;
int (*CompareFunction) (const char*, const char*, int) ;
if (intExactMatch)
CompareFunction = &strcmp_Wrapper;
else
CompareFunction = &strstr_Wrapper;
dir_proc = opendir(PROC_DIRECTORY) ;
if (dir_proc == NULL)
{
perror("Couldn't open the " PROC_DIRECTORY " directory") ;
return (pid_t) -2 ;
}
// Loop while not NULL
while ( (de_DirEntity = readdir(dir_proc)) )
{
if (de_DirEntity->d_type == DT_DIR)
{
if (IsNumeric(de_DirEntity->d_name))
{
strcpy(chrarry_CommandLinePath, PROC_DIRECTORY) ;
strcat(chrarry_CommandLinePath, de_DirEntity->d_name) ;
strcat(chrarry_CommandLinePath, "/cmdline") ;
FILE* fd_CmdLineFile = fopen (chrarry_CommandLinePath, "rt") ; // open the file for reading text
if (fd_CmdLineFile)
{
fscanf(fd_CmdLineFile, "%s", chrarry_NameOfProcess) ; // read from /proc/<NR>/cmdline
fclose(fd_CmdLineFile); // close the file prior to exiting the routine
if (strrchr(chrarry_NameOfProcess, '/'))
chrptr_StringToCompare = strrchr(chrarry_NameOfProcess, '/') +1 ;
else
chrptr_StringToCompare = chrarry_NameOfProcess ;
//printf("Process name: %s\n", chrarry_NameOfProcess);
//printf("Pure Process name: %s\n", chrptr_StringToCompare );
if ( CompareFunction(chrptr_StringToCompare, cchrptr_ProcessName, intCaseSensitiveness) )
{
pid_ProcessIdentifier = (pid_t) atoi(de_DirEntity->d_name) ;
closedir(dir_proc) ;
return pid_ProcessIdentifier ;
}
}
}
}
}
closedir(dir_proc) ;
return pid_ProcessIdentifier ;
}
#ifdef __cplusplus
pid_t GetPIDbyName(const char* cchrptr_ProcessName)
{
return GetPIDbyName(cchrptr_ProcessName, CASE_INSENSITIVE, EXACT_MATCH) ;
}
#else
// C cannot overload functions - fixed
pid_t GetPIDbyName_Wrapper(const char* cchrptr_ProcessName, ... )
{
int intTempArgument ;
int intInputArguments[2] ;
// intInputArguments[0] = 0 ;
// intInputArguments[1] = 0 ;
memset(intInputArguments, 0, sizeof(intInputArguments) ) ;
int intInputIndex ;
va_list argptr;
va_start( argptr, cchrptr_ProcessName );
for (intInputIndex = 0; (intTempArgument = va_arg( argptr, int )) != 15; ++intInputIndex)
{
intInputArguments[intInputIndex] = intTempArgument ;
}
va_end( argptr );
return GetPIDbyName_implements(cchrptr_ProcessName, intInputArguments[0], intInputArguments[1]);
}
#define GetPIDbyName(ProcessName,...) GetPIDbyName_Wrapper(ProcessName, ##__VA_ARGS__, (int) 15)
#endif
int main()
{
pid_t pid = GetPIDbyName("bash") ; // If -1 = not found, if -2 = proc fs access error
printf("PID %d\n", pid);
return EXIT_SUCCESS ;
}
PSおよびその他すべてのツール(カーネルモジュールを除く)は、/proc
から読み取ります。 /proc
は、カーネルによってオンザフライで作成される特別なファイルシステムです。これにより、ユーザーモードプロセスは、他の方法ではカーネルでのみ利用可能なデータを読み取ることができます。
したがって、推奨される方法は、/proc
から読み取ることです。
/proc
ファイルシステムをすばやく直感的に見て、その構造を確認できます。すべてのプロセスには/proc/pid
があり、pidはプロセスID番号です。このフォルダ内には、現在のプロセスに関する異なるデータを含むいくつかのファイルがあります。走ったら
strace ps -aux
プログラムps
が/proc
からこのデータを読み取る方法がわかります。
procps-ng
プロジェクト のライブラリlibprocps
があります。 Ubuntu 13.04では、strace ps
を実行すると、ps
がlibprocps
を使用していることがわかります。
/ procを読み取らずにこれを行う唯一の方法は、「ps aux」を呼び出し、すべての行を調べ、2番目の列(PID)を読み取り、lsof -p [PID]を呼び出します。
.../procを読むことをお勧めします;)
Procの読み取りはそれほど悪くはありません。 C++では表示できませんが、次のDコードは正しい方向を示しています。
import std.stdio; import std.string; import std.file; import std.regexp; import std.c. linux.linux; alias std.string.split explode; string srex = "^/proc/[0-9] + $"; string trex = "State:[\ t] [SR]"; RegExp rex; RegExp rext; string [] scanPidDirs( string target) { string [] result; bool callback(DirEntry * de) { if(de .isdir) { if(rex.find(de.name)> = 0) { string [] a = explode(de.name、 "/"); string pid = a [a.length-1]; string x = cast(string)std.file.read(de.name〜"/status "); int n = rext.find(x); if(n> = 0) { x = cast(string)std.file.read( de.name〜 "/cmdline"); //このiヌル終了 if(x.length)x.length = x.length-1; a = explode(x、 "/"); if(a.length ) x = a [a.length-1]; else x = ""; if(x == target) { result〜= pid〜 "/"〜x; } } } } return true; } listdir( "/ proc"、&callback); return result.dup; } void main(string [] args) { rex = new RegExp(srex); rext = new RegExp(trex); string [] a = scanPidDirs(args [1]); if(!a.length) { writefln( "Not found"); return; } writefln( "%d matching processes"、a.length); foリーチ(s; a) { string [] p = explode(s、 "/"); int pid = atoi(p [0]); writef( "Stop%s(%d)?"、s、pid); string r = readln(); if(r == "Y\n" || r == "y\n ") kill(pid、SIGUSR1); } }