gpt4 book ai didi

C - Lstat on/proc/pid/exe

转载 作者:太空宇宙 更新时间:2023-11-04 00:37:41 24 4
gpt4 key购买 nike

我正在尝试使用 lstat 获取/proc/pid/exe 文件的字节大小。这是我的代码:

int     main(int argc, char *argv[]) 
{
struct stat sb;
char *linkname;
ssize_t r;

if (argc != 2)
{
fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
exit(EXIT_FAILURE);
}

if (lstat(argv[1], &sb) == -1)
{
perror("lstat");
exit(EXIT_FAILURE);
}

printf("sb.st_size %d\n", sb.st_size);

exit(EXIT_SUCCESS);
}

似乎 sb.st_size 总是等于 0,我不明白为什么。另外,此示例是从 readlink(2) 手册页中提取的。

编辑:我正在尝试让它在 openSUSE 上运行。

在此先感谢您的帮助。

最佳答案

/proc 中的文件不是普通文件。对于他们中的大多数人,stat()等。返回 .st_size == 0

特别是,/proc/PID/exe 并不是真正的符号链接(symbolic link)或硬链接(hard link),而是一种特殊的伪文件,其行为大部分类似于符号链接(symbolic link)。

(如果需要,您可以检测 procfs 文件,检查 .st_dev 字段。比较 .st_devlstat("/proc/self/exe",..),例如。)

要根据其 PID 获取特定可执行文件的路径,我推荐一种依赖 readlink() 返回值的方法相反:

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>

/* Creative Commons CC0: Public Domain dedication
* (In jurisdictions without public domain, this example program
* is licensed under the Creative Commons CC0 license.)
*
* To the extent possible under law, Nominal Animal has waived all
* copyright and related or neighboring rights to this example program.
*
* In other words, you are free to use it in any way you wish,
* but if it breaks something, you get to keep all the pieces.
*/

/** exe_of() - Obtain the executable path a process is running
* @pid: Process ID
* @sizeptr: If specified, the allocated size is saved here
* @lenptr: If specified, the path length is saved here
* Returns the dynamically allocated pointer to the path,
* or NULL with errno set if an error occurs.
*/
char *exe_of(const pid_t pid, size_t *const sizeptr, size_t *const lenptr)
{
char *exe_path = NULL;
size_t exe_size = 1024;
ssize_t exe_used;
char path_buf[64];
int path_len;

path_len = snprintf(path_buf, sizeof path_buf, "/proc/%ld/exe", (long)pid);
if (path_len < 1 || path_len >= sizeof path_buf) {
errno = ENOMEM;
return NULL;
}

while (1) {

exe_path = malloc(exe_size);
if (!exe_path) {
errno = ENOMEM;
return NULL;
}

exe_used = readlink(path_buf, exe_path, exe_size - 1);
if (exe_used == (ssize_t)-1)
return NULL;

if (exe_used < (ssize_t)1) {
/* Race condition? */
errno = ENOENT;
return NULL;
}

if (exe_used < (ssize_t)(exe_size - 1))
break;

free(exe_path);
exe_size += 1024;
}

/* Try reallocating the exe_path to minimum size.
* This is optional, and can even fail without
* any bad effects. */
{
char *temp;

temp = realloc(exe_path, exe_used + 1);
if (temp) {
exe_path = temp;
exe_size = exe_used + 1;
}
}

if (sizeptr)
*sizeptr = exe_size;

if (lenptr)
*lenptr = exe_used;

exe_path[exe_used] = '\0';
return exe_path;
}

int main(int argc, char *argv[])
{
int arg;
char *exe;
long pid;
char dummy;

if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
printf("\n");
printf("Usage: %s [ -h | --help ]\n", argv[0]);
printf(" %s PID [ PID ... ]\n", argv[0]);
printf("\n");
return 0;
}

for (arg = 1; arg < argc; arg++)
if (sscanf(argv[arg], " %ld %c", &pid, &dummy) == 1 && pid > 0L) {
exe = exe_of((pid_t)pid, NULL, NULL);
if (exe) {
printf("Process %ld runs '%s'.\n", pid, exe);
free(exe);
} else
printf("Process %ld: %s.\n", pid, strerror(errno));
} else {
printf("%s: Invalid PID.\n", argv[arg]);
return 1;
}

return 0;
}

上面,exe_of() 函数返回伪符号链接(symbolic link) /proc/PID/exe 指向的动态分配副本,可选择存储分配的大小和/或路径长度。 (上面的示例程序不需要它们,所以它们是 NULL。)

这个想法非常简单:分配一个初始动态指针,该指针在大多数情况下都足够大,但又不会大得离谱。为字符串结尾 NUL 字节保留最后一个字节。如果readlink()返回的大小与给它的缓冲区长度相同——它本身不添加终止字符串结尾 NUL 字节——,那么缓冲区可能太短了;丢弃它,分配一个更大的缓冲区,然后重试。

同样,如果你想读取/proc/下的伪文件的全部内容,你不能使用lstat()/stat() 首先找出您可能需要多大的缓冲区;您需要分配一个缓冲区,尽可能多地读取,并在必要时重新分配一个更大的缓冲区。 (我也可以为此展示示例代码。)

有问题吗?

关于C - Lstat on/proc/pid/exe,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24581908/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com