Linux : /proc/<PID>/exe return 位于 '/home/<USER>/new/v' 的进程的可执行文件 '/bin/bash' 的路径
Linux : /proc/<PID>/exe return path to executable '/bin/bash' for process located at '/home/<USER>/new/v'
我正在尝试构建一个脚本,在新进程启动时将 PID 和路径打印到可执行文件。
我的代码如下:
#include<stdio.h>
#include<stdlib.h>
#include <limits.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/time.h>
#include<string.h>
void pnotify(){
int fd,resp,pid,pidbak=0;
fd_set c;
struct timeval tv;
float f;
char buf[256]="",buf2[256]="";
fd=open("/proc/loadavg",O_RDONLY,0600);
if(fd==-1){
printf("Load error !\n");
return;
}
tv.tv_sec=0;
tv.tv_usec=10;
while(1){
FD_ZERO(&c);
FD_SET(fd,&c);
if((resp=select(fd+1,&c,NULL,NULL,&tv))==-1){
printf("Error select.\n");
exit(5);
}
if(resp>0){
pidbak=pid;
read(fd,buf,256);
lseek(fd,0,SEEK_SET);
sscanf(buf,"%f %f %f %s %d",&f,&f,&f,buf,&pid);
memset(buf,0,256);
if(pid != pidbak){
sprintf(buf,"/proc/%d/exe",pid);
if(readlink(buf,buf2,256)<=0){
perror("Readlink Error : ");
continue;
}
printf("PID : %d\tPATH : %s\n",pid,buf2);
}
memset(buf,0,256);
memset(buf2,0,256);
}
}
}
main(){
pnotify();
}
此代码总体上似乎运行良好,但是,当我打开另一个新终端执行新进程时,其可执行文件位于 /home/<USER>/new/v
,它提供的路径位于 /bin/bash
。
你能找出问题所在吗?
一切正常。 'v' 是一个 shell 脚本,而 /bin/bash 是
实际上是 运行 的可执行进程。你也许能得到
/proc/$$/cmdline(或 comm)中的更多信息,具体取决于什么
您实际要解决的问题。或者,您可以使用
监控 fork 和 exec 调用的 netlink 接口。
注意当一个新进程启动时,它有相同的可执行文件
作为其 parent.
我想通了,
每当我们 运行 来自终端的代码 (/bin/bash
) if forks fork()
一个带有新 PID
的新进程(child 终端 /bin/bash
和新的 PID)然后这个 child 调用 exec()
并用 v
覆盖自己。在 fork()
和 exec()
之间有一个很小的时间间隔,直到这段时间 /proc/PID/exe
指向 /bin/bash
并且当 v
起来 & 运行ning /proc/PID/exe
更新为指向“/home/USER/v”。
我相应地修改了代码,现在它可以正常工作了。
#include<stdio.h>
#include<stdlib.h>
#include <limits.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/time.h>
#include<string.h>
void pnotify(){
int fd,resp,pid,pidbak=0,flag=0;
fd_set c;
struct timeval tv;
float f;
char buf[256]="",buf2[256]="";
fd=open("/proc/loadavg",O_RDONLY,0600);
if(fd==-1){
printf("Load error !\n");
return;
}
tv.tv_sec=0;
tv.tv_usec=10;
while(1){
FD_ZERO(&c);
FD_SET(fd,&c);
if((resp=select(fd+1,&c,NULL,NULL,&tv))==-1){
printf("Error select.\n");
exit(5);
}
if(resp>0){
pidbak=pid;
read(fd,buf,256);
lseek(fd,0,SEEK_SET);
sscanf(buf,"%f %f %f %s %d",&f,&f,&f,buf,&pid);
memset(buf,0,256);
if(pid != pidbak){
sprintf(buf,"/proc/%d/exe",pid);
do{
memset(buf2,0,256);
if(readlink(buf,buf2,256)<=0){
perror("Readlink Error : ");
flag==1;
break;
}
}while(strcmp(buf2,"/bin/bash")==0);
if(flag==1)
continue;
printf("PID : %d\tPATH : %s\n",pid,buf2);
}
memset(buf,0,256);
memset(buf2,0,256);
}
}
}
main(){
pnotify();
}
这不能可靠地工作。您正在滥用 loadavg 中的 "last pid" 字段。在您从 select 中醒来并阅读它之间,以及在解析和使用该数字做某事之间,您有一个 window ,其中可以有大量进程来来去去,而您对此一无所知发生了。
也许有专门的设施来监控 forks/execs,我不知道。在最坏的情况下,您可以通过在 clone/execve/whatever 您真正想要监视的
上放置探测器来保证使用 systemtap 的可靠通知。
我正在尝试构建一个脚本,在新进程启动时将 PID 和路径打印到可执行文件。
我的代码如下:
#include<stdio.h>
#include<stdlib.h>
#include <limits.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/time.h>
#include<string.h>
void pnotify(){
int fd,resp,pid,pidbak=0;
fd_set c;
struct timeval tv;
float f;
char buf[256]="",buf2[256]="";
fd=open("/proc/loadavg",O_RDONLY,0600);
if(fd==-1){
printf("Load error !\n");
return;
}
tv.tv_sec=0;
tv.tv_usec=10;
while(1){
FD_ZERO(&c);
FD_SET(fd,&c);
if((resp=select(fd+1,&c,NULL,NULL,&tv))==-1){
printf("Error select.\n");
exit(5);
}
if(resp>0){
pidbak=pid;
read(fd,buf,256);
lseek(fd,0,SEEK_SET);
sscanf(buf,"%f %f %f %s %d",&f,&f,&f,buf,&pid);
memset(buf,0,256);
if(pid != pidbak){
sprintf(buf,"/proc/%d/exe",pid);
if(readlink(buf,buf2,256)<=0){
perror("Readlink Error : ");
continue;
}
printf("PID : %d\tPATH : %s\n",pid,buf2);
}
memset(buf,0,256);
memset(buf2,0,256);
}
}
}
main(){
pnotify();
}
此代码总体上似乎运行良好,但是,当我打开另一个新终端执行新进程时,其可执行文件位于 /home/<USER>/new/v
,它提供的路径位于 /bin/bash
。
一切正常。 'v' 是一个 shell 脚本,而 /bin/bash 是 实际上是 运行 的可执行进程。你也许能得到 /proc/$$/cmdline(或 comm)中的更多信息,具体取决于什么 您实际要解决的问题。或者,您可以使用 监控 fork 和 exec 调用的 netlink 接口。
注意当一个新进程启动时,它有相同的可执行文件 作为其 parent.
我想通了,
每当我们 运行 来自终端的代码 (/bin/bash
) if forks fork()
一个带有新 PID
的新进程(child 终端 /bin/bash
和新的 PID)然后这个 child 调用 exec()
并用 v
覆盖自己。在 fork()
和 exec()
之间有一个很小的时间间隔,直到这段时间 /proc/PID/exe
指向 /bin/bash
并且当 v
起来 & 运行ning /proc/PID/exe
更新为指向“/home/USER/v”。
我相应地修改了代码,现在它可以正常工作了。
#include<stdio.h>
#include<stdlib.h>
#include <limits.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/time.h>
#include<string.h>
void pnotify(){
int fd,resp,pid,pidbak=0,flag=0;
fd_set c;
struct timeval tv;
float f;
char buf[256]="",buf2[256]="";
fd=open("/proc/loadavg",O_RDONLY,0600);
if(fd==-1){
printf("Load error !\n");
return;
}
tv.tv_sec=0;
tv.tv_usec=10;
while(1){
FD_ZERO(&c);
FD_SET(fd,&c);
if((resp=select(fd+1,&c,NULL,NULL,&tv))==-1){
printf("Error select.\n");
exit(5);
}
if(resp>0){
pidbak=pid;
read(fd,buf,256);
lseek(fd,0,SEEK_SET);
sscanf(buf,"%f %f %f %s %d",&f,&f,&f,buf,&pid);
memset(buf,0,256);
if(pid != pidbak){
sprintf(buf,"/proc/%d/exe",pid);
do{
memset(buf2,0,256);
if(readlink(buf,buf2,256)<=0){
perror("Readlink Error : ");
flag==1;
break;
}
}while(strcmp(buf2,"/bin/bash")==0);
if(flag==1)
continue;
printf("PID : %d\tPATH : %s\n",pid,buf2);
}
memset(buf,0,256);
memset(buf2,0,256);
}
}
}
main(){
pnotify();
}
这不能可靠地工作。您正在滥用 loadavg 中的 "last pid" 字段。在您从 select 中醒来并阅读它之间,以及在解析和使用该数字做某事之间,您有一个 window ,其中可以有大量进程来来去去,而您对此一无所知发生了。
也许有专门的设施来监控 forks/execs,我不知道。在最坏的情况下,您可以通过在 clone/execve/whatever 您真正想要监视的
上放置探测器来保证使用 systemtap 的可靠通知。