A Glance at the [APUE] Process

Posted by JOWP on Tue, 07 May 2019 21:05:03 +0200

Basic concepts

Program: Executable file stored in disk file

Processes: Instances of program execution

Cmd: ps ,top

Process ID: Each process has a unique process ID identified by a non-negative integer

0 is the dispatch process, 1 is the init process, (most UNIX systems) 2 is the page daemon

/*In addition to the process ID, a process can return other identifiers using the following functions*/

#include <unistd.h>

pid_t getpid(void);                           Return: The process that invoked the process ID   
pid_t getppid(void);                          Return: The parent process of the calling process ID   
uid_t getuid(void);                           Return: The actual user who invoked the process ID   
uid_t geteuid(void);                          Return: Valid user calling process ID   
gid_t getgid(void);                           Return: Actual group of the calling process ID   
gid_t getegid(void);                          Return: A valid group of calling processes ID  

Create process

fork()

In linux, the only way to create a new process is for an existing process to call the fork() function. The newly created process is a child process, and the existing process is called the parent process.

#include <unistd.h>

pid_t fork(void);

The fork() function is a system call, and when the parent process calls fork(), fork() returns two values: the parent process returns the pid of the child process, which is an integer greater than 0, and the child process returns 0.Parent and child processes continue to execute statements after fork(), and child processes inherit copies of the parent's data space, stack, and stack, but do not share storage space.copy-on-write technology: The kernel changes permissions (data segments, stacks, and stacks) to read-only, and if either parent or child process wants to modify the copy, the kernel makes only one copy of the memory in the modification area, usually a page in virtual memory.

Two uses of fork():

1. A parent process duplicates itself so that the parent and child processes execute different code snippets at the same time

2. A parent process copies itself to execute different programs

vfork()

#include <unistd.h>

pid_t vfork();

The difference between vfork() and fork():

1.vfork child and parent processes share data segments, fork does not share

2.vfork's child process executes before the parent process, and the parent process does not begin execution until it calls exec or exit

Terminate process

There are five ways a process can terminate normally and three ways it can terminate abnormally

Normal termination:

1. Use return in main function

2. Call the eixt function

3. Call the _exit or _Exit function

4. The last thread of the process executes the return statement in its startup routine

5. The last thread of the process calls pthread_exit

Abnormal termination:

1. Call abort()

2. When the process receives certain signals

3. The last thread responds to the Cancel request

No matter how the process terminates, the same piece of code installed by the kernel is executed.This code closes all descriptors of the process and releases its memory

If the parent process terminates before the child process ends, the child process becomes an orphan and init becomes the adoptive parent of the process

A process that has been terminated but the parent process has not been untreated becomes a zombie, ps state Z

atexit

#include <stdlib.h>

int atexit(void (*func)(void));

Atexit is an exit process registration function.Exit executes atexit-registered functions first, and executes them several times, then executes them later.

Exit and_exit

The difference is that exit first performs some cleanup (such as flushing I/O) and then returns to the kernel, while _exit and _Exit return directly to the kernel

wait and waitpid

#include <unistd.h>

pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);

Both wait and waitpid are blocked functions, but waitpid can be set to non-blocking and option to WNOHANG

Family of exec functions

#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,
           ..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],
            char *const envp[]);

//Examples: execlp("/bin/echo", "echo", "hello", (char *)0)

system()

#include <stdlib.h>

int system(const char *cmdsting);

system can execute a command in a program

Process Accounting

Process accounting is created and written when processes are created and terminated, so processes that are executing all the time do not have process accounting files, such as init processes

Process Scheduling

Processes can modify priority by changing the nice value, the higher the nice value, the lower the priority

#include <unistd.h>
#include <sys/resource.h>

int nice(int nice);
int getpriority(int which, id_t who);
int setpriority(int which, id_t who, int value);

nice values are based on 0~2*NZERO-1,

NZERO is available through sysconf (_SC_NZERO)

nice() can return -1, so Return-1 cannot determine failure, and you need to check if errno is not zero at the same time

Process Time

#include <sys/times.h>
#include <sys/resource.h>

struct rusage {
    struct timeval ru_utime; /* user CPU time used */
    struct timeval ru_stime; /* system CPU time used */
    long   ru_maxrss;        /* maximum resident set size */
    long   ru_ixrss;         /* integral shared memory size */
    long   ru_idrss;         /* integral unshared data size */
    long   ru_isrss;         /* integral unshared stack size */
    long   ru_minflt;        /* page reclaims (soft page faults) */
    long   ru_majflt;        /* page faults (hard page faults) */
    long   ru_nswap;         /* swaps */
    long   ru_inblock;       /* block input operations */
    long   ru_oublock;       /* block output operations */
    long   ru_msgsnd;        /* IPC messages sent */
    long   ru_msgrcv;        /* IPC messages received */
    long   ru_nsignals;      /* signals received */
    long   ru_nvcsw;         /* voluntary context switches */
    long   ru_nivcsw;        /* involuntary context switches */
};

clock_t times(struct tms *buf);
int getrusage(int who, strcut rusage*rusage);

 

Topics: Unix Linux