Linux/Linux_Source

Linux - ps 프로세스 리스트 출력 프로그램 및 소스

sosal 2010. 1. 26. 23:07
반응형

/*
 http://sosal.tistory.com/
 * made by so_Sal
 */


이 포스팅에서 다루는 내용

  ::  DIR *opendir(const char *dirname);
  ::  int readdir(unsigned int fd, struct dirent *dirp, unsigned  int count);
  ::  struct dirent{};
  ::  int closedir(DIR *dir);
  ::  int lstat(const char* path, struct stat* buf);
  ::  struct stat{};
  ::  ==================예제==================


#include<sys/types.h>
#include<dirent.h>

DIR *opendir(const char *dirname);

opendir() 함수는 매개변수 dirname에 해당하는 디렉토리 스트림을 열고,
그 디렉토리 스트림에 대한 포인터를 반환합니다.
포인터가 가리키는 디렉토리의 첫번째 항목을 가리킵니다.




#include<unistd.h>
#include<linux/dirent.h>
#include<linux/unistd.h>


int readdir(unsigned int fd, struct dirent *dirp, unsigned  int count);

readdir() 함수는 파일 서술자 fd에 의해 지목된 디렉토리에서
dirp에 의해 포인트된 메모리 지역에 있는 dirent 구조체를 읽어, DIR*에 저장한다.
3번째 매개변수 count 인자는 메모리 공간의 크기이지만, 무시 가능하다.




#include<dirent.h>

dirent 구조체는 다음과 같이 선언된다.
 struct dirent
{
    long d_ino;                                /* 아이노드 */
    off_t d_off;                                 /* dirent 의 offset */
    unsigned short d_reclen;            /* d_name 의 길이 */
    char d_name [NAME_MAX+1];   /* 파일 이름(없다면 NULL로 종료) */
}

dirent 구조체는 파일, 또는 디렉토리가 가지고 있는 정보 구조체이다.

d_ino :: 는 파일이 가지고 있는 자신만의 번호 inode를 가리키는 숫자이다.
d_off  :: 는 디렉토리의 시작에서 dirent까지의 거리를 말한다.
d_reclen :: 파일 혹은 디렉토리의 이름의 길이이다. (NULL을 포함하지 않는다.)
d_name :: 파일 혹은 디렉토리의 이름이다. (NULL이라면 파일 없음을 의미)

return :: 성공 : 1, 실패 : -1.


#include <sys/types.h>
#include <dirent.h>

int closedir(DIR *dir);

closedir() 함수는 dir과 연관된 디렉토리 스트림을 닫습니다.
디렉토리 스트림 서술자 dir은 위 함수 호출 이후에는 유효하지 않습니다.
return : 성공시 0, 실패시 -1


#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>


int
stat(const char* path, struct stat* buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char* path, struct stat* buf);

이 함수는 지정된 파일에 대한 정보를 반환한다. 정보를 얻기위해 필요한 접근 권한은 없지만,
파일이 위치하는 디렉토리의 읽기 권한 (탐색 권한)은 필요하다.
stat과 lstat은 동일시 되고, 경로는 절대경로, 상대경로, dirent 구조체의 d_name으로도 판별한다.
fstat은 경로가 아닌, open이나 socket, pipe 등으로 반환된
파일 서술자로 접근하는 함수이다.


struct  stat
{
    dev_t        st_dev;              /* device */
    ino_t         st_ino;              /* inode */
   mode_t   st_mode      /* protection */
    nlink_t      st_nlink;           /* number of hard links */
    uid_t         st_uid;              /* user ID of owner */
    gid_t         st_gid;              /* group ID of owner */
    dev_t        st_rdev;            /* device type (if inode device) */
    off_t          st_size             /* total size, in bytes */
    blksize_t   st_blksize;        /* blocksize for filesystem I/O */
    blkcnt_t     st_blocks;        /* number of blocks allocated */
    time_t       st_atime;          /* time of last access */
    time_t       st_mtime;        /* time of last modification */
    time_t       st_ctime;         /* time of last change */
//메뉴얼 페이지를 참조하였습니다.

stat 구조체입니다. 파일이 가지는 정보를 가져올 수 있도록 하는 구조체입니다.
각각의 구조체 변수들은 이름이나 간단한 주석으로 쉽게 아실거라 생각됩니다.
특히, st_mode 는 파일의 형식정보가 반환되는 변수입니다.
파일 형식과 접근 권한, 특성 등을 아래 메크로를 통해서 확인할 수 있습니다.

S_ISLNK(file_mode)     //is it a symbolic link?
S_ISREG(file_mode)    //regular file?
S_ISDIR(file_mode)     //directory?
S_ISCHR(file_mode)    //character device?
S_ISBLK(file_mode)     //block device?
S_ISFIFO(file_mode)    //fifo?
S_ISSOCK(file_mode) //socket?









===================================== 예제 =====================================

/*
 * 리눅스/유닉스 환경에서 모든 프로세스는 파일로 되어있습니다.
 *   /proc 디렉토리에 자신의 pid로 디렉토리가 생성되며,
 *   /proc/pid/cmdline 이란 파일로부터 프로세스 이름을 알 수 있습니다.
 */



#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>

int main() {
    DIR *dir;                       //  /proc/pid/ 를 가리킬 DIR* 변수
    struct dirent *entry;        // 각 파일의 inode를 통해 파일을 선택할 dirent 구조체
    struct stat fileStat;          // 파일의 정보를 담는 구조체

    int pid;                         // 프로세스는 /proc 디렉토리에 자신의 pid로 파일을 담아 둡니다.
    char cmdLine[256];
    char tempPath[256];

    printf("Processes Info\n");

    dir = opendir("/proc");   //  /proc이란 디렉토리 스트름이 대한 포인터가 반환되었습니다.

    while ((entry = readdir(dir)) != NULL) {   //   /proc에 존재하는 파일들을 차례대로 읽습니다.
        lstat(entry->d_name, &fileStat);          // DIR*가 가리키는 파일의 state 정보를 가져온다.
  
      if (!S_ISDIR(fileStat.st_mode))            // is dir? 디렉토리인지 확인한다.
             continue;                                    // 프로세스는 /proc에 자신의 pid로 디렉토리를
                                                              // 만드는 점을 안다면 이해하실거라 생각합니다.


        pid = atoi(entry->d_name);          // 프로세스(디렉토리)인것을 확인하면, 숫자로 반환한다.
        if (pid <= 0) continue;                       // 숫자가 아니라면 다시 continue;

        sprintf(tempPath, "/proc/%d/cmdline", pid); // cmdline :: 프로세스 이름이 적힌파일
        getCmdLine(tempPath, cmdLine);     // /proc/pid/cmdline에서 프로세스의 이름을
                                                             // 가져오는 함수로 보냅니다. 아래에 정의되어있습니다.

        printf("[%d] %s\n", pid, cmdLine);
    }
    closedir(dir);
}

int
getCmdLine(char *file, char *buf) {
    FILE *srcFp;
    int i;
    srcFp = fopen(file, "r");            //   /proc/pid/cmdline에 이름이 있습니다.

    memset(buf, 0, sizeof(buf));
    fgets(buf, 256, srcFp);
    fclose(srcFp);
}