Write ps commands in C Language
When I was studying Unix/Linux programming practice tutorials, I always felt that I could not learn anything, and I was not impressed after that. After I consulted my senior brother, I did not have to do this myself, I was not able to understand it in depth, so I was asked to write a simple ps command. At first, it was very big. After continuous efforts, we could finally implement the simple ps command function. I would like to share with you some suggestions or errors. Let's talk about our own ideas and understand the following small questions: 1. What is the use of ps? 2. How is ps system called? 3. Where is process information stored? Man ps can find that ps is used to display process instantaneous information. It has many parameters, which are not described here. The next step is to view ps system calls, which can be implemented using the strace command, some outputs are as follows: wKiom1YWbvPSDEj_AAE07dWqhWs177.jpg can get a lot of useful information from the strace output information, files And Directories (/proc/$ {pid},/proc/$ {pid}/stat,/proc/$ {pid }/ status ); run the "ps-e" command to output all processes, and then switch to the/proc directory to view them. It is found that all the pure numbers in the directory are named as processes, switch to this directory and open the file mentioned above. The file contains process-related information. Next, to implement simple ps commands, You need to traverse/proc to get the wkiom1ywdqgacxfoaafpm9p2epq118.jpg file in the directory. The implementation code is as follows:
# Include <stdio. h> # include <unistd. h> # include <sys/stat. h> # include <string. h> # include <stdlib. h> # include <sys/types. h> # include <dirent. h> # include <pwd. h> # define MAX_LEN 20 struct ps_info * trav_dir (char dir []); int read_info (char d_name [], struct ps_info * p1); void print_ps (struct ps_info * head ); int is_num (char *); void uid_to_name (); typedef struct ps_info {char pname [MAX_LEN]; char user [MAX_LEN]; int pi D; int ppid; char state; struct ps_info * next;} mps; int main (int ac, char * av []) {mps * head, * link; head = trav_dir ("/proc/"); if (head = NULL) printf ("traverse dir error \ n"); print_ps (head); while (head! = NULL) // release the linked list {link = head; head = head-> next; free (link);} return 0;} mps * trav_dir (char dir []) {DIR * dir_ptr; mps * head, * p1, * p2; struct dirent * direntp; struct stat infobuf; if (dir_ptr = opendir (dir) = NULL) fprintf (stderr, "dir error % s \ n", dir); else {head = p1 = p2 = (struct ps_info *) malloc (sizeof (struct ps_info )); // create a linked list while (direntp = readdir (dir_ptr ))! = NULL) // traverse all process directories in the/proc directory {if (is_num (direntp-> d_name) = 0) // determine whether the directory name is a pure number {if (p1 = NULL) {printf ("malloc error! \ N "); exit (0);} if (read_info (direntp-> d_name, p1 )! = 0) // obtain process information {printf ("read_info error \ n"); exit (0);} p2-> next = p1; // Insert the new node p2 = p1; p1 = (struct ps_info *) malloc (sizeof (struct ps_info) ;}} p2-> next = NULL; return head ;} int read_info (char d_name [], struct ps_info * p1) {FILE * fd; char dir [20]; struct stat infobuf; sprintf (dir, "% s/% s ", "/proc/", d_name); chdir ("/proc"); // switch to the/proc directory. Otherwise, stat returns-1 if (stat (d_name, & infobuf) =-1) // get process USER fprintf (st Derr, "stat error % s \ n", d_name); else // p1-> user = uid_to_name (infobuf. st_uid); uid_to_name (infobuf. st_uid, p1); chdir (dir); // switch to the/proc/pid directory if (fd = fopen ("stat", "r") <0) {printf ("open the file is error! \ N "); exit (0 );}
While (4 = fscanf (fd, "% d % s % c % d \ n", & (p1-> pid), p1-> pname, & (p1-> state), & (p1-> ppid) // read the content of the first four fields of the file and store them in the linked list members.
{Break;} fclose (fd); return 0;} void uid_to_name (uid_t uid, struct ps_info * p1) // obtain the owner user {struct passwd * getpwuid (), * pw_ptr; static char numstr [10]; if (pw_ptr = getpwuid (uid) of the process from the process uid )) = NULL) {sprintf (numstr, "% d", uid); strcpy (p1-> user, numstr);} else strcpy (p1-> user, pw_ptr-> pw_name);} int is_num (char p_name []) {int I, len; len = strlen (p_name); if (len = 0) return-1; for (I = 0; I <len; I ++) if (p_nam E [I] <'0' | p_name [I]> '9') return-1; return 0;} void print_ps (struct ps_info * head) {mps * list; printf ("USER \ t \ tPID \ tPPID \ tSTATE \ tPNAME \ n"); for (list = head; list! = NULL; list = list-> next) {printf ("% s \ t % d \ t % c \ t % s \ n ", list-> user, list-> pid, list-> ppid, list-> state, list-> pname );}}