Linux API 列出正在运行的进程?
- 2024-10-09 09:10:00
- admin 原创
- 75
问题描述:
我需要一个 C/C++ API,它允许我列出 Linux 系统上正在运行的进程,并列出每个进程打开的文件。
我不想直接读取 /proc/ 文件系统。
有人能想到办法做到这一点吗?
解决方案 1:
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 ,该 API 应该在您的存储库中可用(或者应该说已经安装),但您需要使用“-dev”变体来获取标题和其他内容。
祝你好运
解决方案 2:
如果你不想从 /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]
",task->comm , task->pid);
}
return 0;
}
void cleanup_module(void) {
printk(KERN_INFO "Cleaning Up.
");
}
上面的代码取自我的文章 http://linuxgazette.net/133/saha.html 。一旦您有了自己的系统调用,您就可以从用户空间程序中调用它。
解决方案 3:
下面是(C/C++):
您可以在这里找到它:
http ://ubuntuforums.org/showthread.php?t=657097
本质上,它所做的就是循环遍历中的所有数字文件夹/proc/<pid>
,然后对执行 readlink /proc/<pid>/exe
,或者如果你想要命令行参数cat /proc/<pid>/cmdline
进程打开的文件描述符在 中/proc/<pid>/fd/<descriptor>
,您可以通过在每个符号链接上执行 readlink 来获取文件名,例如readlink /proc/<pid>/fd/<descriptor>
。fd 可以是设备(如 /dev/null)、套接字或文件,甚至可能更多。
包括 <unistd.h>
ssize_t readlink(const char path, char buf, size_t bufsiz);
成功时,readlink() 返回 buf 中放置的字节数。
出错时,返回 -1 并设置 errno 以指示错误。
顺便说一句,这与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
", chrarry_NameOfProcess);
//printf("Pure Process name: %s
", 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
", pid);
return EXIT_SUCCESS ;
}
解决方案 4:
如果你不这样做,那么我猜你使用的任何 API 最终都会读取 /proc 文件系统。以下是一些执行此操作的程序示例:
每秒
顶部
进程
但不幸的是,这并不构成 API。
解决方案 5:
/proc
PS 和从中读取的所有其他工具(内核模块除外)/proc
都是内核动态创建的特殊文件系统,以便用户模式进程可以读取原本只能由内核使用的数据。
因此,推荐的方式是从 读取/proc
。
您可以快速直观地查看/proc
文件系统以了解其结构。每个进程都有一个/proc/pid
pid 是进程 ID 号。此文件夹中有多个文件,其中包含有关当前进程的不同数据。如果您运行
strace ps -aux
您将看到程序如何ps
从中读取这些数据/proc
。
解决方案 6:
不读取 /proc 的情况下执行此操作的唯一方法是调用“ps aux”,遍历每一行,读取第二列(PID)并用它调用 lsof -p [PID]。
...我建议阅读/proc;)
解决方案 7:
libprocps
该procps-ng
项目有一个库。在 Ubuntu 13.04 上,如果您执行strace ps
,则可以看到ps
使用libprocps
。
解决方案 8:
读取 proc 并不难。我无法用 C++ 向您展示,但以下 D 代码应该可以为您指明正确的方向:
导入 std.stdio;
导入 std.string;
导入 std.文件;
导入 std.regexp;
导入 std.c.linux.linux;
别名 std.string.split 爆炸;
字符串 srex = "^/proc/[0-9]+$";
字符串 trex = "状态:[ ][SR]";
正则表达式 rex;
正则表达式 rext;
字符串[] scanPidDirs(字符串目标)
{
字符串[]结果;
bool 回调(DirEntry* de)
{
如果 (de.isdir)
{
如果 (rex.find(de.name) >= 0)
{
字符串[] a = explosive(de.name, "/");
字符串pid = a[a.length-1];
字符串 x = cast(string) std.file.read(de.name ~ "/status");
int n = rext.find(x);
如果 (n >= 0)
{
x = cast(string) std.file.read(de.name ~ "/cmdline");
// 这是以空值结尾的
如果(x.长度)x.长度=x.长度-1;
a = 爆炸(x,“/”);
如果 (a.长度)
x = a[a.长度-1];
别的
x =“”;
如果 (x == 目标)
{
结果 ~= pid ~ "/" ~x;
}
}
}
}
返回 true;
}
listdir(“/proc”,&callback);
返回结果.dup;
}
void main(字符串[] 参数)
{
rex = 新的 RegExp(srex);
rext = 新的 RegExp(trex);
字符串[] a = scanPidDirs(args[1]);
如果 (!a.长度)
{
writefln("未找到");
返回;
}
writefln("%d 个匹配的进程", a.length);
foreach (s; a)
{
字符串[] p = 爆炸(s,“/”);
int pid = atoi(p[0]);
writef("停止 %s (%d)?", s, pid);
字符串 r = readln();
如果 (r == "Y
" || r == "y
")
杀死(pid,SIGUSR1);
}
}
解决方案 9:
通过名称轻松找到任何进程的 pid
pid_t GetPIDbyName(char* ps_name)
{
FILE *fp;
char *cmd=(char*)calloc(1,200);
sprintf(cmd,"pidof %s",ps_name);
fp=popen(cmd,"r");
fread(cmd,1,200,fp);
fclose(fp);
return atoi(cmd);
}
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件