我试图让大小在/ proc /进程/ EXE与LSTAT文件的字节。 这里是我的代码:
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
是不是真的符号链接或硬链接,而是一个特殊的伪文件,其行为大多喜欢一个符号链接。
(如果你需要,你可以检测procfs的文件检查.st_dev
领域。相较于.st_dev
从获得lstat("/proc/self/exe",..)
例如。)
要获取的路径,基于其PID特定execubtable,我建议的方法依靠的返回值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()
函数返回,其中所述伪符号链接的动态分配的拷贝/proc/PID/exe
点,任选地存储所述分配的大小和/或路径长度太。 (示例程序上面并不需要他们,所以他们是NULL。)
这个想法很简单:分配初始动态指针是大多数情况下足够大,但不是大得离谱。 保留最后一个字节的结束串NUL字节。 如果返回的大小readlink()
是一样的给它的缓冲区长度-它不添加终结结束串NUL字节本身- ,则缓冲区可能已经过短; 丢弃它,分配更大的缓冲器,和重试。
同样,如果你想读一个伪文件下的全部内容/proc/
,您不能使用lstat()
/ stat()
首先要搞清楚,你可能会缓冲多大需要; 你需要分配一个缓冲区,多读就可以了,并在必要时,只是重新分配一个更大的缓冲区。 (我可以显示该示例代码了。)
有问题吗?
无法在我要回复很抱歉后发表评论!
Valgrind的将报告exe_path = malloc(exe_size);
在标称动物的职位为“块肯定已失去”。 所以,如果你正在使用的功能,那么你的记忆力会上升得非常快。
即使释放内存当您返回NULL会解决这个问题。 还应该增加从调用的malloc(字符*)的显式转换,使您使用-Wall GCC停止抱怨
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];
unsigned 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 = (char*)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) {
free(exe_path);
return NULL;
}
if (exe_used < (ssize_t)1) {
/* Race condition? */
errno = ENOENT;
free(exe_path);
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 = (char*)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;
}
一般来说,你不必担心这一点,但名义动物评论后,似乎从/ proc / PID / EXE Linux的限制文件路径由PAGE_SIZE。 因此,即使文件系统支持长于路径,有没有办法让的readlink()给你这条道路,因为这是作为一个硬限制来实现。 我已经找到了另一种方式,所以如果执行的readlink失败ENAMETOOLONG,你可以阅读的/ proc / PID /地图,虽然这可能是碰碰运气,我发现它击中每个进程都在4个不同的发行版除非不具有系统进程实际文件名(ENOENT)
int getExecutableFromMaps(char *buf, size_t bufsize) {
FILE *fp;
char *mylinebuf = NULL;
size_t mylinebufsize = 0;
size_t counter = 0;
size_t start = 0;
size_t column = 0;
int result = -1;
fp = fopen("/proc/self/maps", "r");
if( fp != NULL ) {
if( getline(&mylinebuf, &mylinebufsize, fp) >= 0 ) {
if( mylinebuf != NULL ) {
while( column < 5 && counter < mylinebufsize ) {
while( counter < mylinebufsize && mylinebuf[counter] != ' ') {
counter++;
}
while( counter < mylinebufsize && mylinebuf[counter] == ' ') {
counter++;
}
column++;
}
int start = counter;
while( counter < mylinebufsize && (mylinebuf[counter] != '\n' && mylinebuf[counter] != '\r') ) {
counter++;
}
if( counter <= mylinebufsize && start < counter && (counter-start+1)<=bufsize ) {
memcpy(buf, &mylinebuf[start], counter-start);
buf[counter-start+1] = 0;
result = counter-start+1;
}
}
}
if( mylinebuf != NULL ) {
free(mylinebuf);
}
fclose(fp);
}
return result;
}
注:这是补充代码只应被调用后的readlink失败,因为这是昂贵的。