Linux子进程

1.fork()函数概述

在Linux程序中,用fork()可以创建一个子进程,具体而言:

  • 调用fork()时,会创建当前进程的一份拷贝;
  • 当前进程称为父进程(parentprocess),新创建的进程称为子进程(childprocess);
  • 从fork()调用点开始,父子进程都开始执行。

2.区分父子进程

2.1fork()函数

[email protected]:~$man fork | more

FORK(2) Linux Programmer‘s Manual FORK(2)

NAME

fork- create a child process

SYNOPSIS

#include<unistd.h>

pid_tfork(void);

DESCRIPTION

fork() creates a new process by duplicating the calling process. The

newprocess, referred to as the child, is an exact duplicate of the

calling process, referred to as the parent, except for the following

points:

* The child has its own unique process ID, and this PID does not match

theID of any existing process group (setpgid(2)).

* The child‘s parent process ID is the same as the parent‘s process

ID.

* The child does not inherit its parent‘s memory locks (mlock(2),

mlockall(2)).

* Process resource utilizations (getrusage(2)) and CPU time counters

(times(2))are reset to zero in the child.

* The child‘s set of pending signals is initially empty (sigpend‐

ing(2)).

* The child does not inherit semaphore adjustments from its parent

(semop(2)).

* The child does not inherit record locks from its parent (fcntl(2)).

* The child does not inherit timers from its parent (setitimer(2),

alarm(2),timer_create(2)).

* The child does not inherit outstanding asynchronous I/O operations

fromits parent (aio_read(3), aio_write(3)), nor does it inherit any

asynchronousI/O contexts from its parent (see io_setup(2)).

The process attributes in the preceding list are all specified in

POSIX.1-2001. The parent and child also differ with respect to the

followingLinux-specific process attributes:

* The child does not inherit directory change notifications (dnotify)

fromits parent (see the description of F_NOTIFY in fcntl(2)).

* The prctl(2) PR_SET_PDEATHSIG setting is reset so that the child

doesnot receive a signal when its parent terminates.

* Memory mappings that have been marked with the madvise(2) MADV_DONT‐

FORKflag are not inherited across a fork().

* The termination signal of the child is always SIGCHLD (see

clone(2)).

Notethe following further points:

* The child process is created with a single thread—the onethat

calledfork(). The entire virtual address space of the parent is

replicated in the child, including the states of mutexes, condition

variables,and other pthreads objects; the use of pthread_atfork(3)

maybe helpful for dealing with problems that this can cause.

* The child inherits copies of the parent‘s set of open file descrip‐

tors. Each file descriptor in the child refers to the same open

file description (see open(2)) as the corresponding file descriptor

inthe parent. This means that the two descriptors share open file

status flags, current file offset, and signal-driven I/O attributes

(seethe description of F_SETOWN and F_SETSIG in fcntl(2)).

* The child inherits copies of the parent‘s set of open message queue

descriptors (see mq_overview(7)). Each descriptor in the child

refersto the same open message queue description as the correspond‐

ing descriptor in the parent. This means that the two descriptors

sharethe same flags (mq_flags).

* The child inherits copies of the parent‘s set of open directory

streams (see opendir(3)). POSIX.1-2001 says that the corresponding

directorystreams in the parent and child may share the directory

streampositioning; on Linux/glibc they do not.

RETURNVALUE

Onsuccess, the PID of the child process is returned in the parent, and

0is returned in the child. On failure, -1 is returned in the parent,

nochild process is created, and errno is set appropriately.

ERRORS

EAGAINfork() cannot allocate sufficient memory to copy the parent‘s

pagetables and allocate a task structure for the child.

EAGAINIt was not possible to create a new process because the caller‘s

RLIMIT_NPROC resource limit was encountered. To exceed this

limit,the process must have either the CAP_SYS_ADMIN or the

CAP_SYS_RESOURCEcapability.

ENOMEMfork() failed to allocate the necessary kernel structures

becausememory is tight.

CONFORMINGTO

SVr4,4.3BSD, POSIX.1-2001.

NOTES

UnderLinux, fork() is implemented using copy-on-write pages, so the

only penalty that it incurs is the time and memory required to dupli‐

catethe parent‘s page tables, and to create a unique task structure

forthe child.

Since version 2.3.3, rather than invoking the kernel‘s fork() system

call,the glibc fork() wrapper that is provided as part of the NPTL

threading implementation invokes clone(2) with flags that provide the

sameeffect as the traditional system call. The glibc wrapper invokes

anyfork handlers that have been established using pthread_atfork(3).

EXAMPLE

Seepipe(2) and wait(2).

SEEALSO

clone(2), execve(2), setrlimit(2), unshare(2), vfork(2), wait(2), dae‐

mon(3),capabilities(7), credentials(7)

COLOPHON

Thispage is part of release 3.35 of the Linux man-pages project. A

description of the project, and information about reporting bugs, can

befound at http://man7.org/linux/man-pages/.

Linux 2009-04-27 FORK(2)

[email protected]:~$

2.2判别方法

当fork()之后,需要区分父进程和子进程,以便执行各自正确的路径。

具体来讲,根据fork()返回的pid的值来区分父子进程:返回者为0,表示该进程是子进程;如果大于0则表示父进程。当返回-1的时候表示fork()调用异常。

3.示例

这里取《AdvancedLinux Programming》Listing3.3的代码:

#include<stdio.h>

#include<sys/types.h>

#include<unistd.h>

intmain()

{

pid_tchild_pid;

printf("themain program process ID is %d\n", (int)getpid());

child_pid= fork();

if(child_pid != 0) {

printf("thisis the parent process, with id %d\n", (int)getpid());

printf("thechild‘s process ID is %d\n", (int)child_pid);

}else {

printf("thisis the child process, with id %d\n", (int)getpid());

}

return0;

}

执行结果:

[email protected]:~/examples/cpp/fork$gcc fork_list3_3.c

[email protected]:~/examples/cpp/fork$./a.out

themain program process ID is 3161

thisis the parent process, with id 3161

thechild‘s process ID is 3162

thisis the child process, with id 3162

[email protected]:~/examples/cpp/fork$

4.进程等待

4.1退出时机

fork()之后,父进程和子进程谁先执行完?或者说,哪个进程先结束?

答案是,由父子进程本身的代码决定;并不是说子进程先结束、然后父进程再结束。

为此,我们给出一个例子进行说明。其中父进程sleep10秒钟,子进程sleep20秒。同时,用ps命令来观测当前存在的进程列表。

在ALPListing 3.3的基础上,增加两个sleep()调用,修改如下:

#include<stdio.h>

#include<sys/types.h>

#include<unistd.h>

intmain()

{

pid_tchild_pid;

printf("themain program process ID is %d\n", (int)getpid());

child_pid= fork();

if(child_pid != 0) {

printf("thisis the parent process, with id %d\n", (int)getpid());

printf("thechild‘s process ID is %d\n", (int)child_pid);

sleep(10);

}else {

printf("thisis the child process, with id %d\n", (int)getpid());

sleep(20);

}

return0;

}

我们打开两个终端,一个执行上面的程序,另外一个不断用ps观察进程。

第一个终端的执行结果:

[email protected]:~/examples/cpp/fork$./a.out

themain program process ID is
3392

thisis the parent process, with id 3392

thechild‘s process ID is
3393

thisis the child process, with id 3393

[email protected]:~/examples/cpp/fork$

另外一个终端的观测结果:

[email protected]:~$ps -a

PIDTTY TIME CMD

3363pts/3 00:00:00 man

3374pts/3 00:00:00 pager

3392pts/0 00:00:00 a.out

3393pts/0 00:00:00 a.out

3394pts/1 00:00:00 ps

[email protected]:~$ps -a

PIDTTY TIME CMD

3363pts/3 00:00:00 man

3374pts/3 00:00:00 pager

3393pts/0 00:00:00 a.out

3395pts/1 00:00:00 ps

[email protected]:~$ps -a

PIDTTY TIME CMD

3363pts/3 00:00:00 man

3374pts/3 00:00:00 pager

3398pts/1 00:00:00 ps

[email protected]:~$

可以看到,子进程先结束,而后父进程结束。

4.2父进程等待子进程

实际项目中,父进程往往需要等待子进程结束,然后决定后续处理流程;进一步地,需要了解子进程是如何退出的:正常退出、异常退出,等等。

为此,需要使用waitfamily系统调用。

waitfamily有4种形式:

  • wait():父进程等待其中一个子进程退出(exit或异常终止);
  • waitpid():父进程等待指定的子进程退出;
  • wait3()& wait4():检查子进程的状态,比如资源信息。

使用较多的是waitpid()。

4.3子进程退出的几种方式

有如下几种退出方式:

  • 子进程调用exit()或return;
  • 子进程异常退出,比如除零错误等;
  • 其他异常终止???。

对于这几种方式,父进程可以wait()获取退出方式。以下给出每一种方式的代码示例,但总的调用形式如下:

intstatus;

waitpid(child_pid,&status, 0);

/*see "man waitpid" for detail */

if(WIFEXITED(status)) {

printf("exited,status=%d\n", WEXITSTATUS(status));

}else if (WIFSIGNALED(status)) {

printf("killedby signal %d\n", WTERMSIG(status));

}else if (WIFSTOPPED(status)) {

printf("stoppedby signal %d\n", WSTOPSIG(status));

}else {

printf("unknown\n");

}

4.3.1exit()或return

exit()或return均属于正常退出,也是子进程最常见的一种退出方式。对应于:

if(WIFEXITED(status)) {

printf("exited,status=%d\n", WEXITSTATUS(status));

}

return的示例:

#include<stdio.h>

#include<sys/types.h>

#include<unistd.h>

#include<sys/wait.h>

#include<stdlib.h>

voidchild_foo(int exit_code)

{

printf("child_foo()\n");

exit(exit_code);// or return exit_code

}

intget_exit_code(int argc, const char* argv[])

{

if(argc != 2) {

printf("Usage:%s exit_code\n", argv[0]);

exit(-1);

}

//ignore other exceptions

returnatoi(argv[1]);

}

intmain(int argc, const char* argv[])

{

pid_tchild_pid;

int exit_code = get_exit_code(argc, argv);

printf("themain program process ID is %d\n", (int)getpid());

child_pid= fork();

/*child process */

if(child_pid == 0) {

child_foo(exit_code);

}

/*parent process */

intstatus;

waitpid(child_pid,&status, 0);

/*see "man waitpid" for detail */

if(WIFEXITED(status)) {

printf("exited,status=%d\n", WEXITSTATUS(status));

}else if (WIFSIGNALED(status)) {

printf("killedby signal %d\n", WTERMSIG(status));

}else if (WIFSTOPPED(status)) {

printf("stoppedby signal %d\n", WSTOPSIG(status));

}else {

printf("unknown\n");

}

return0;

}

执行结果:

[email protected]:~/examples/cpp/wait$./a.out 1

themain program process ID is 2635

child_foo()

exited,status=1

[email protected]:~/examples/cpp/wait$./a.out 12

themain program process ID is 2637

child_foo()

exited,status=12

[email protected]:~/examples/cpp/wait$

在有了上面的示例之后,我们给出ALP3.4 Process Termination的一段话:

Normally,a process terminates in one of two ways. Either the executing programcalls the
exit function, or the program’s mainfunction returns. Each process has an exit code: a number that theprocess returns to its parent. The exit code is the argument passedto the
exit function, or the value returned from main.

4.3.2异常返回&信号

进程还会因为异常而退出,比如除零异常(SIGFPE)、段异常(SIGSEGV,SegmentFault)、abort()对应的SIGABRT异常,等等。

将上面的代码修改如下:

#include<stdio.h>

#include<sys/types.h>

#include<unistd.h>

#include<sys/wait.h>

#include<stdlib.h>

voidtest_SIGFPE()

{

inti;

for(i = 10; i >= 0; i--) {

printf("%d%d\n", i, 100 / i);

}

}

voidtest_SIGABRT()

{

printf("thechild process will abort.\n");

abort();

printf("unreachablestatement.\n");

}

intget_abnormal_type(int argc, const char* argv[])

{

inttype;

if(argc != 2 || (type = atoi(argv[1]), type != 1 && type != 2)){

printf("Usage:%s [1|2]\n", argv[0]);

printf(" 1: SIGFPE, 2: SIGABRT\n");

exit(-1);

}

returntype;

}

intmain(int argc, const char* argv[])

{

pid_tchild_pid;

int type = get_abnormal_type(argc, argv);

child_pid= fork();

/*child process */

if(child_pid == 0) {

type== 1 ? test_SIGFPE() : test_SIGABRT();

return0; // unreachable

}

/*parent process */

intstatus;

waitpid(child_pid,&status, 0);

/*see "man waitpid" for detail */

if(WIFEXITED(status)) {

printf("exited,status=%d\n", WEXITSTATUS(status));

}else if (WIFSIGNALED(status)) {

printf("killedby signal %d\n", WTERMSIG(status));

}else if (WIFSTOPPED(status)) {

printf("stoppedby signal %d\n", WSTOPSIG(status));

}else {

printf("unknown\n");

}

return0;

}

执行结果:

[email protected]:~/examples/cpp/wait$./a.out 1

1010

911

812

714

616

520

425

333

250

1100

killedby signal 8

[email protected]:~/examples/cpp/wait$./a.out 2

thechild process will abort.

killedby signal 6

[email protected]:~/examples/cpp/wait$

各个信号的定义在/usr/include/asm-generic/signal.h,如下:

[email protected]:~$cat /usr/include/asm-generic/signal.h

#ifndef__ASM_GENERIC_SIGNAL_H

#define__ASM_GENERIC_SIGNAL_H

#include<linux/types.h>

#define_NSIG 64

#define_NSIG_BPW __BITS_PER_LONG

#define_NSIG_WORDS (_NSIG / _NSIG_BPW)

#defineSIGHUP 1

#defineSIGINT 2

#defineSIGQUIT 3

#defineSIGILL 4

#defineSIGTRAP 5

#defineSIGABRT 6

#defineSIGIOT 6

#defineSIGBUS 7

#defineSIGFPE 8

#defineSIGKILL 9

#defineSIGUSR1 10

#defineSIGSEGV 11

#defineSIGUSR2 12

#defineSIGPIPE 13

#defineSIGALRM 14

#defineSIGTERM 15

#defineSIGSTKFLT 16

#defineSIGCHLD 17

#defineSIGCONT 18

#defineSIGSTOP 19

#defineSIGTSTP 20

#defineSIGTTIN 21

#defineSIGTTOU 22

#defineSIGURG 23

#defineSIGXCPU 24

#defineSIGXFSZ 25

#defineSIGVTALRM 26

#defineSIGPROF 27

#defineSIGWINCH 28

#defineSIGIO 29

#defineSIGPOLL SIGIO

/*

#defineSIGLOST 29

*/

#defineSIGPWR 30

#defineSIGSYS 31

#define SIGUNUSED 31

/*These should not be considered constants from userland. */

#defineSIGRTMIN 32

#ifndefSIGRTMAX

#defineSIGRTMAX _NSIG

#endif

通常构造一个异常比较棘手,为此测试的时候可以直接调用kill()函数,传入异常退出对应的信号值。如下:

#include<stdio.h>

#include<sys/types.h>

#include<unistd.h>

#include<sys/wait.h>

#include<stdlib.h>

/*

Usage:./a.out signal_code

e.g../a.out 5

*/

intmain(int argc, const char* argv[])

{

pid_tchild_pid;

child_pid= fork();

if(child_pid == 0) {

printf("childprocess is sleeping.\n");

sleep(100);

return0;

}

sleep(2);// Give a chance for child process to print a line.

kill(child_pid,atoi(argv[1]));

intstatus;

waitpid(child_pid,&status, 0);

if(WIFEXITED(status)) {

printf("exited,status=%d\n", WEXITSTATUS(status));

}else if (WIFSIGNALED(status)) {

printf("killedby signal %d\n", WTERMSIG(status));

}else if (WIFSTOPPED(status)) {

printf("stoppedby signal %d\n", WSTOPSIG(status));

}else {

printf("unknown\n");

}

return0;

}

5.僵尸进程&孤儿进程

前面简单讨论过父进程和子进程谁先退出的问题,这里进一步讨论。

5.1进程退出信息

前面已讨论,wait&waitpid等函数可获取子进程退出时的一些信息,比如是正常退出还是异常退出。或者说,子进程退出时,Linux内核为每个(已终止的)子进程都保存了一些信息,包括进程ID、进程退出时的状态(exitcode
or signal info),等等。如此父进程调用wait&waitpid的时候,就可以获取这些信息。

5.2僵尸进程

Zombieprocess,
也称defunctprocess。通俗地解释,就是父进程还没有执行完,或父进程调用wait之前,子进程就已经执行完毕(terminated)。进程执行的时候,称为活的;相对应地,执行玩了,或终止执行了,进程就die了,死了,所以就称为zombieprocess
or defunct process。

维基(http://en.wikipedia.org/wiki/Zombie_process)的一段话:

Theterm zombie process derives from the common definition of zombie —an undead person. In the term‘s metaphor, the child process has"died"
but has not yet been "reaped".

5.3孤儿进程

和僵尸进程对应地,称为孤儿进程(orphanprocess)。即父进程执行完了,终止了,但子进程仍在执行。此时,子进程的parent不存在了,所以就称为孤儿进程。

——当然,这里的父进程终止的时候,没有针对子进程调用wait。

在父进程终止的时候,孤儿进程会被init进程所领养(adopted,reparenting)。

5.4示例分析

接下来通过一个例子来说明以上概念。我们通过sleep()的时长来控制父子进程的运行时间,且通过命令行参数输入这两个sleep时长,从而简化示例代码的长度。——为了简化,同样少了许多异常处理流程。代码如下:

5.4.1僵尸进程

[email protected]:~/examples/cpp/zombile_orphan_process$./a.out 20 10

Parentprocess‘s pid: 2944

thisis the parent process, with id 2944

thechild‘s process ID is 2945

thisis the child process, with id 2945

childprocess will be terminated.

parentprocess will be terminated.

[email protected]:~/examples/cpp/zombile_orphan_process$

ps查看两个进程的状态:

1)父子进程均在运行:

2714 2705 Ss bash

2821 1 Sl gedit/home/flying-bird/examples/cpp/zombile_orphan_process/zombie_orphan_process.c

2846 2 S [kworker/0:3]

2870 2705 Ss bash

2943 2 S [kworker/0:2]

2944 2714 S+ ./a.out 20 10

2945 2944 S+ ./a.out 20 10

2947 2870 R+ ps -e -o pid,ppid,stat,cmd

2)子进程终止(僵尸)、父进程仍在运行:

2714 2705 Ss bash

2821 1 Sl gedit/home/flying-bird/examples/cpp/zombile_orphan_process/zombie_orphan_process.c

2846 2 S [kworker/0:3]

2870 2705 Ss bash

2943 2 S [kworker/0:2]

2944 2714 S+ ./a.out 20 10

2945 2944 Z+ [a.out] <defunct>

2948 2870 R+ ps -e -o pid,ppid,stat,cmd

3)父子进程均终止

2714 2705 Ss+ bash

2821 1 Sl gedit/home/flying-bird/examples/cpp/zombile_orphan_process/zombie_orphan_process.c

2846 2 S [kworker/0:3]

2870 2705 Ss bash

2943 2 S [kworker/0:2]

2949 2870 R+ ps -e -o pid,ppid,stat,cmd

5.4.2ps命令显示进程状态码的含义

manps:

PROCESSSTATE CODES

Hereare the different values that the s, stat and state output

specifiers(header "STAT" or "S") will display to describethe state of

aprocess:

D uninterruptible sleep (usually IO)

R running or runnable (on run queue)

S interruptible sleep (waiting for an event to complete)

T stopped, either by a job control signal or because it is being

traced.

W paging (not valid since the 2.6.xx kernel)

X dead (should never be seen)

Z defunct ("zombie") process, terminated but not reaped byits

parent.

ForBSD formats and when the stat keyword is used, additional

charactersmay be displayed:

< high-priority (not nice to other users)

N low-priority (nice to other users)

L has pages locked into memory (for real-time and custom IO)

s is a session leader

l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)

+ is in the foreground process group.

5.4.3父进程终止时,对应的僵尸进程的处理

通过上面的例子及ps结果,可以看到当父进程终止时,僵尸进程也消失了(aregone)。其原理在于,当父进程终止时,该父进程的所有子进程都将被init进程所继承。而init程序会自动清除所继承的僵尸进程。

所以,在上面的例子中,当父进程运行结束之后,子进程也自动消失掉了。

5.4.4孤儿进程

接下来再构造孤儿进程的例子。

[email protected]:~/examples/cpp/zombile_orphan_process$./a.out 10 20

Parentprocess‘s pid: 3684

thisis the parent process, with id 3684

thechild‘s process ID is 3685

thisis the child process, with id 3685

parentprocess will be terminated.

[email protected]:~/examples/cpp/zombile_orphan_process$child process will be terminated.

下面是ps观测结果。

1)父子进程均在运行

2714 2705 Ss bash

2821 1 Rl gedit/home/flying-bird/examples/cpp/zombile_orphan_process/zombie_orphan_process.c

2870 2705 Ss bash

3038 2 S [kworker/1:1]

3079 2 S [kworker/0:3]

3646 2 S [kworker/0:0]

3666 2 S [kworker/0:2]

3684 2714 S+ ./a.out 10 20

3685 3684 S+ ./a.out 10 20

3688 2870 R+ ps -e -o pid,ppid,stat,cmd

2)父进程执行完毕、子进程仍在运行(变成孤儿进程被init收养)

2714 2705 Ss+ bash

2821 1 Rl gedit/home/flying-bird/examples/cpp/zombile_orphan_process/zombie_orphan_process.c

2870 2705 Ss bash

3038 2 S [kworker/1:1]

3079 2 S [kworker/0:3]

3646 2 S [kworker/0:0]

3666 2 S [kworker/0:2]

3685 1 S ./a.out 10 20

3689 2870 R+ ps -e -o pid,ppid,stat,cmd

3)子进程运行完毕

2714 2705 Ss+ bash

2821 1 Sl gedit/home/flying-bird/examples/cpp/zombile_orphan_process/zombie_orphan_process.c

2870 2705 Ss bash

3038 2 S [kworker/1:1]

3079 2 S [kworker/0:3]

3646 2 S [kworker/0:0]

3666 2 S [kworker/0:2]

3690 2870 R+ ps -e -o pid,ppid,stat,cmd

参考资料

ALP:http://download.csdn.net/download/shmilyy/720746

Linux子进程

时间: 2024-12-17 21:16:18

Linux子进程的相关文章

shell中export理解误区

一直以来,以为shell脚本中经过export后的变量会影响到执行这个shell的终端中的环境变量.环境变量这个概念不是shell所独有的,而是linux里面进程所拥有的,shell解释器运行起来就是一个进程,这样它也就有了自己的环境变量.通常linux下main函数写法有: 1 int main(void) 2 int main(int argc, char **argv) 3 int main(int argc, char **argv, char **envp) 常见的为前2种写法,第三种

subprocess

python2.x 中使用os 模块来在执行系统命令. 其中两个方法值得关注 os.sys('df -h') os.Popen('df -h') 其中os.sys() 最终返回的是执行命令的成功与否的状态 而os.Popen() 就相当于开启了一个临时文件,把执行结果放到这个临时文件中.于是你想得到执行结果就需要os.Popen('df -h').read() python3.x 中执行系统命令就不要再用os模块了,因为有subprocess模块,必定人要往前看,别用一些过时的技术. subpr

调用程序继承fd和监听端口的问题

linux子进程或者popen.exec启动的程序都会继承fd 比如主进程调用了另一个程序,结果主程序结束后,这个被调用程序竟然继承了所有的fd包括监听端口,有时候阻塞运行时间比较长,会导致监听端口收不到报文.后来实验建立子进程去启动程序,写个脚本去启动程序,情况是一样的.写个小程序再去启动脚本,也一样. 查了下文档,使用fcloseall来关闭fd,结果发现这个函数没用,别的系统没有试验,至少在centos6.3和redhat5.7都不行. 最后直接在子进程里面从3到1000的fd全部clos

Linux下异步回收子进程

背景 我们知道,当一个进程fork出子进程后,没有对子进程进行回收,那么子进程运行完之后的状态会变为僵尸进程. 我们可以通过wait和waitpid来回收子进程,防止僵尸进程的出现. 但是wait和waitpid,要么以阻塞方式运行,要么以轮询方式运行,都极大的占用了CPU资源. 本文将介绍,父进程如何通过异步操作回收子进程! 原理 在每个子进程运行完成之后,都会向父进程发出SIGCHLD信号.而在默认情况下,父进程会忽略掉该信号.因此,我们只需要对SIGCHLD信号进行捕捉,即可异步对子进程进

LINUX系统编程 由REDIS的持久化机制联想到的子进程退出的相关问题

19:22:01 2014-08-27 引言: 以前对wait waitpid 以及exit这几个函数只是大致上了解,但是看REDIS的AOF和RDB 2种持久化时 均要处理子进程运行完成退出和父进程需要做的什么事情,所以特定看了UNIX环境编程和LINUX系统编程这2本书 重新梳理下整个要点. 内容: 一般而言: 如果程序类似于下面的情况: if((pid=fork())==0) { dochildtthing(); exit(0); } else if(pid>0) { dofathertt

Linux间的进程通信;以及子进程的创建

1 "-----第六天-----------------------------------------------------------------------------" 2 3 1.版本控制:svn/git; 4 5 2.进程的概念: 6 1)程序和进程: 7 每个进程操作系统会为它分配 0-4G 的虚拟内存空间(32位操作系统): 其中0-3G为用户内存空间,进程可以对它进行读写操作: 3G - 4G 为系统内核空间,进程没有读写权限. 8 进程只能读写用户空间,没有权限读

Linux系统开发 4 进程资源 环境 fork()子进程 wait() waitpid()僵尸 孤儿进程

<大纲> Linux系统编程 进程资源上限 进程环境变量 进程获取/修改环境变量 创建子进程fork() 最大进程数测试 程序的设置用户ID/组ID/黏住位 exec簇函数,执行程序覆盖堆栈 fork 与execl函数在一起 exec() 与主程序同一个PCB 僵尸进程 wait()回收僵尸进程 证明:父子进程同组pid waitpid() 非阻塞等待子线程发生变化 孤儿进程演示[父进程已经结束,子进程还在运行] 进程资源上限值 [email protected]:~$ cat /proc/s

linux进程编程:子进程创建及执行函数简介

子进程创建及执行函数有三个: (1)fork();(2)exec();(3)system();    下面分别做详细介绍.(1)fork()    函数定义:    pid_t fork();    函数说明:    linux下进程在内存中由三部分数据组成:代码段.数据段.堆栈段.在一个进程中,调用fork函数,可以创建.启动一个新进程.新进程与父进程共享代码段,复制父进程的数据段和堆栈段.创建成功后,fork()会向两个进程都有返回值.向父进程的返回值为子进程的进行号,向子进程的返回值为0.

windows、linux创建子进程

在windows下创建子进程较常用到的API就是CreateProcess,可以通过以下的方式启动一个新进程: STARTUPINFO si = {0};                 PROCESS_INFORMATION pi = {0};     si.cb = sizeof(STARTUPINFO);         //结构体大小    GetStartupInfo(&si);                       //初始化结构    si.wShowWindow = SW_