Process
System Programming
" One vision, one purpose. "
Copyright © Tony's Studio 2020 - 2022
Chapter Six - Process
6.1 Meet Process
6.1.1 Program and Process
Program is a passive entity, and is stored in hard disk. Process is an active entity, and got a Program Counter and a whole set of resources and runs. When an executable is loaded into memory, it becomes a process.
6.1.2 Process State
new
: under creationrunning
: literallywaiting
: waiting for some events, e.g. I/O or signalready
: waiting for processer arrangementterminated
: process finished
6.2 Start and Exit
“Action speaks louder than words.”
6.2.1 Start Process
6.2.1.1 fork
fork()
is a common way to create an identical process.
1
2
pid_t fork();Parent process return child process’s pid and child process return 0 if succeeded. Otherwise -1 is returned and we can use
perror()
to show error info.
6.2.1.2 exec
There are a lot of these stuffs.
1
2
3
4
5
6
7
8
int execl(const char *pathname, const char *arg0, ... /* (char *)0 */);
int execv(const char *pathname, char *const argv[]);
int execle(const char *pathname, const char *arg0, .../* (char *)0, char *const envp[] */);
int execve(const char *pathname, char *const argv[], char *const envp[]);
int execlp(const char *filename, const char *arg0, ... /* (char *)0 */);
int execvp(const char *filename, char *const argv[]);
int fexecve(int fd, char *const argv[], char *const envp[]);All arguments should end with
NULL
. Onlyexecve
is a system call.
- “
l
“ for list, soargv
is an argument list.- “
v
“ for vector, soargv
is an array.- “
e
“ for environment, to containenvp
array. If no such thing, default environment variables will be passed rather than no environment.- “
p
“ for environmentPATH
, it indicates that system should go toPATH
to findfilename
.Notice that, unlike we type in commands in terminal, executable name won’t be added by default to the argument list, and need to be added manually. So, the two ways below have different output. It depends on how the target program parse its arguments. If use
arg[i]
directly, it may cause some error, whilegetopt()
may hide some errors.
1
2 execvp("ls", "-l", NULL); // equal to $ ls
execvp("ls", "ls", "-l", NULL); // equal to $ ls -l
6.2.2 Exit Process
6.2.2.1 Exit Process
We can wait until process until return in main, or use exit functions to exit somewhere else.
1
2
3
4
5
6
void exit(int status); // Do some cleaning, and then go to kernal.
void _Exit(int status); // Go to kernal directly.
void _exit(int status); // GO to kernal directly.When
exit()
is called, program will flush buffer stream, call functions that registered byatexit()
andon_ext
and other functions related toexit()
, then call_exit()
at last.
6.2.2.2 Exit Status
We can get a process’ exit status by waiting it.
1
2
3
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
wait()
will jam current process until any of the child process returns, and itself return the pid of the returned child process.
waitpid()
can wait for a specific process, and is more complicated.
pid meaning > 0 wait for specific child process with given pid = 0 wait for any child process whose group id is the same as current process = -1 wait for any child process, same as wait()
< -1 wait for any child process whose group id is the same as |pid|
options
meaning WNOHANG
no block, if no child process returns, return immediately WUNTRACED
return immediately if child process goes into waiting status 0 same as wait()
However, there is one more thing. When we want to wait for a process and get its return status, we need something more.
WIFEXITED
indicates whether process is exited normally or not, and returns a boolean value, not 0 means true. Then, we useWEXITSTATUS
to get the exit status.
1
2
3
4
5 if (waitpid(-1, &status, 0) > 0)
{
if (WIFEXITED(status) != 0)
printf("Exit status: %d\n", WEXITSTATUS(status));
}Similarly,
WIFSIGNALED
indicates whether process is stopped by a signal, withWTERMSIG
to tell which signal it was.
6.3 Special Process
6.3.1 Some Concepts
- Process Group: 进程组是一组进程的集合,由进程组PID表示。 每个进程必须有一个进程组PID,即必须属于某个进程组,一个终端的控制进程是它所发起的一系列进程的进程组。
- Session: 会话期是由一个或者多个进程组组成的集合,开始于用户登录,结束于用户退出,在此期间,用户所运行的所有进程属于该会话期。
6.3.2 Daemon Process
Code is more convincing, huh?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 /*
Create a daemon process.
*/
int main(void)
{
// Step 1: Create a child process and terminate the parent.
pid_t pid = fork();
if (pid < 0)
{
fprintf(stderr, "Fork error!\n");
return -1;
}
else if (pid > 0)
return 0;
// Child process now becomes an orphan.
// Step 2: Detach the child process by creating a new session.
setsid();
// Step 3: Change working directory, or current directory can't be deleted.
chdir("./");
// Step 4: Change file access mask.
umask(0);
// Step 5: Close file descriptions, no interactions.
for (int i = 0; i < 3; i++)
close(i);
// Now, the real work of daemon starts, print log info to a temp file.
int fd;
int cnt = 0;
char buffer[32];
for (; ; )
{
if ((fd = open("/tmp/daemon.log", O_WRONLY | O_CREAT | O_APPEND, 0600)) < 0)
{
perror("open");
exit(1);
}
sprintf(buffer, "Execute Order %d\n", cnt);
write(fd, buffer, strlen(buffer));
close(fd);
if (cnt == 66)
break;
cnt++;
sleep(10);
}
return 0;
}For the header files… hard to remember.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void perror ( const char * str );
int setsid(void);
int chdir(const char *path);
pid_t fork();
mode_t umask(mode_t mask);
int open(const char *pathname, int flags, ...);
int close(int fd);
size_t write(int fd, void *buffer, size_t nbytes);
6.3.3 Zombie Process
If child process dies before parent, and parent doesn’t wait for it, which means it is not cleaned in time, then the child process will become a zombie process, and marked with [defunct] is process list.
One zombie is not that serious, but too many zombies may use up system pid, which prevent other processes to be created.
One more thing, zombie can not be killed by
kill -9
, it can only be released when parent wait for it, or parent exited, or system rebooted.
6.3.4 Orphan Process
If parent process exited before child process, then the child will become an orphan. We don’t want orphan, so it will then be taken care of by
init
process.
" Do or do not. There is no try. "
Copyright © Tony's Studio 2020 - 2022