使用IO操作实现ps-ef的功能
本文主要介绍使用IO操作实现ps-ef的功能,其中使用的主要函数接口有fopen, opendir,readdir,fgets,getpwuid,getgrgid以及字符串操作函数,一方面能够复习IO操作,另一方面能更快熟悉进程的相关知识,是一个不错的进程入门的小练习!
下面是用到的所有头文件:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
以下主要是功能函数,由于进程都是有进程号的,一般进程都在/proc的文件夹下保存,所以首先要识别哪一个是进程号,此后再进行USER、PID、PPID、GROUP 、 STAT、 COMMAND的解析;
//判断一个字符串是否为数字
int isNum(const char *str)
{
while (*str)
{
if (*str >= '0' && *str <= '9')
{
++str;
continue;
}
break;
}
if (*str != '\0')
{
return 0;
}
return 1;
}
//解析并打印PID PPID USER GROUP STAT COMMAND
int parseData(const char *pathname)
{
FILE *fp = NULL;
char *ptmp = NULL;
char tmpbuff[1024] = {0};
char pid[128] = {0};
char ppid[128] = {0};
char cmd[128] = {0};
char stat[128] = {0};
char uid[128] = {0};
char gid[128] = {0};
struct passwd *puid;
struct group *pgid;
uid_t Uid = -1;
gid_t Gid = -1;
fp = fopen(pathname, "r");
if (NULL == fp)
{
perror("fail to fopen\n");
return -1;
}
while (1)
{
memset(tmpbuff, 0, sizeof(tmpbuff));
ptmp = fgets(tmpbuff, sizeof(tmpbuff), fp);
if (NULL == ptmp)
{
break;
}
if (!strncmp(tmpbuff, "Pid", 3))
{
strtok(tmpbuff, "\t");
strcpy(pid, strtok(NULL, "\n"));
}
else if (!strncmp(tmpbuff, "PPid", 4))
{
strtok(tmpbuff, "\t");
strcpy(ppid, strtok(NULL, "\n"));
}
else if (!strncmp(tmpbuff, "Name", 4)) //获得cmd
{
strtok(tmpbuff, "\t");
strcpy(cmd, strtok(NULL, "\n"));
}
else if (!strncmp(tmpbuff, "State", 5))
{
strtok(tmpbuff, "\t");
strcpy(stat, strtok(NULL, " "));
}
else if (!strncmp(tmpbuff, "Uid", 3)) //获得USER
{
strtok(tmpbuff, "\t");
strcpy(uid, strtok(NULL, "\t"));
Uid = atoi(uid);
puid = getpwuid(Uid);
}
else if (!strncmp(tmpbuff, "Gid", 3)) //获得GROUP
{
strtok(tmpbuff, "\t");
strtok(gid, strtok(NULL, "\t"));
Gid = atoi(gid);
pgid = getgrgid(Gid);
}
else
{
continue;
}
}
printf("%9s%8s%8s%9s%8s %s\n", puid->pw_name, pid, ppid, pgid->gr_name, stat, cmd);
fclose(fp);
return 0;
}
//打开存放PID等项的文件
void myPs(void)
{
DIR *dp = NULL;
struct dirent *pp = NULL;
char path[1024] = {0};
dp = opendir("/proc/");
if (NULL == dp)
{
perror("fail to opendir");
return ;
}
printf(" USER PID PPID GROUP STAT COMMAND\n");
while (1)
{
pp = readdir(dp);
if (NULL == pp)
{
break;
}
if (isNum(pp->d_name))
{
sprintf(path, "/proc/%s/status", pp->d_name); //拼接进程路径(/proc/进程号/status),文件内保存了进程的基本信息
parseData(path);
}
}
closedir(dp);
return ;
}
以下是在主函数中进行功能函数的调用:
int main(int argc, const char *argv[])
{
myPs();
return 0;
}
本期的分享就到这里结束了,不懂得小伙伴欢迎私信留言提问哦!