c语言多进程编程,C语言中的多进程

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

序言

为了充分利用计算机中的多核CPU,计算机提供了两个接口使用多核CPU,两个接口分别是:多进程、多线程。本编文章将介绍多进程编程,利用多核CPU。

多进程核的个数与可同时运行的进程数相同。相反,若进程数超过核数,进程将分时使用CPU资源。但因为CPU运行速度极快,我们会感到所有进程同时运行。当然多核越多,这种感觉也明显。

fork函数创建多进程1

2

3pid_t fork(void);

fork函数将创建调用的进程副本。两个进程都将执行fork调用后的语句,子进程将复制父进程相同的内存空间,之后的程序流要根据fork函数的返回值加以区分。父进程:fork函数返回子进程ID

子进程:fork函数返回0

fork%E5%87%BD%E6%95%B0%E5%88%9B%E5%BB%BA%E8%BF%9B%E7%A8%8B.png

eg.1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22#include

int gval = 10;

int (){

pid_t pid;

int lval = 20;

gval++, lval += 5;

pid = fork();

if (pid == 0) {

gval += 2, lval += 2;

} else {//parent pro

gval -= 2, lval -= 2;

}

if (pid == 0) {

printf("Child Proc: [%d, %d] n", gval, lval);

} else {

printf("Parent Proc: [%d, %d] n", gval, lval);

}

}

运行结果:

fork.png

进程与僵尸进程

僵尸进程的产生

文件操作中,关闭文件和打开文件同等重要。同样进程的创建和进程的销毁同等重要。如果未认真对待进程销毁,它们将变成僵尸进程困扰各位。

进程完成工作后(执行完main函数中的程序后)应当销毁,但有时这些进程将变成僵尸进程,占用系统中的重要资源。

子进程的终止方式:传递参数并调用exit函数

main函数中执行return语句并返回值

向exit函数传递的参数值和main函数的return语句返回的值都会传递给操作系统。而操作系统并不会销毁子进程,直到把这些值传递给产生该子进程的父进程。

eg.1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17#include

int (){

pid_t pid = fork();

if (pid == 0) { Child Pro

printf("Hi, I am a child process n");

} else {

printf("Child Process ID: %d n", pid);

}

if (pid) {

puts("End child process n");

} else {

printf("End parent process n");

}

}

销毁僵尸进程

为了销毁子进程,父进程应主动请求获取子进程的返回值。

使用wait函数1

2

3

4#include

pid wait(int * statloc);

//成功时返回终止的子进程的ID,失败时返回-1

调用此函数时如果已有子进程终止,那么子进程终止时传递的返回值(exit函数的参数值、main函数的return返回值)将保存到该函数的参数所指内存空间。WIFEXITED子进程正常终止时返回”真“ true

WEXITSTATUS返回子进程的返回值

eg.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#include

#in

int (){

int status;

pid_t pid = fork();

if (pid == 0) {

return 3;

} else {

printf("Child PID:%d n", pid);

pid = fork();

if (pid == 0) {

exit(7);

} else {

wait(&status);

if (WIFEXITED(status)) {

printf("Child send one: %d n", WEXITSTATUS(status));

}

wait(&status)

if (WIFEXITED(status)) {

printf("Child send tow: %d n", WEXITSTATUS(status));

}

sleep(30);

}

}

}

运行结果:

wait.png

调用wait函数时,如果没有已终止的子进程,那么程序将阻塞(Blocking)直到有子进程终止。

使用waitpid函数

wait函数会引起程序阻塞,而waitpid即使没有终止的子进程也不会进入阻塞状态,而是返回0并退出。1

2

3

4

5

6

7

8

9#include

pid_t waitpid(pid_t pid, int * statloc, int options);

//成功时返回终止的子进程ID(或0),失败时返回-1

//1. pid 等待终止的目标子进程的ID, 若传递-1,则与wait函数相同,可以等待任意子进程终止

//2. ...

//3. 传递头文件sys/wait.h中声明的常量WNOHANG,即使没有终止的子进程也不会进入阻塞状态,而是返回0并退出

调用waitpid时程序不会阻塞。

eg.1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21#include

#include

int (){

int status;

pid_t pid = fork();

if (pid == 0) {

return 24;

} else {

while (!waitpid(-1, &status, WNOHANG)) {

sleep(3);

printf("sleep 3sec n");

}

if (WIFEXITED(status)) {

printf("Child send %d n", WEXITSTATUS(status));

}

}

return 0;

}

运行结果:

waitpid.h

信号处理

signal函数

信号注册函数1

2

3

4

5

6

7#include

void (*signal(int signo, void (*func)(int)))(int);

//函数名: signal

//参数:int signo, void (*func)(int)

//返回类型:参数为int类型,返回void型函数指针

发生第一个参数代表的情况时,调用第二个参数所指向的函数。

signal函数中注册的部分特殊情况和对应的常数。SIGALRM: 已通过调用alarm函数注册的时间

SIGINT: 输入CTRL+C

SIGCHLD: 子进程终止

注册好信号后,发生注册信号时(注册的情况发生时),操作系统将调用该信号对应的函数。1

2#include

unsigned int alarm(unsigned int seconds);

如果调用该函数的同时向它传递一个正整型参数,相应时间后(以秒为单位)将产生SIGALRM信号。若向该函数传递0,则之前对SIGALRM信号的预约将取消。

eg.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#include

#include

#include

void timeout(int sig){

if (sig == SIGALRM) {

puts("Time out!");

}

alarm(2);

};

void keycontrol(int sig){

if (sig == SIGINT) {

puts("CTRL+C");

}

}

int (){

int i;

signal(SIGALRM, timeout);

signal(SIGINT, keycontrol);

alarm(2);

for (int i = 0; i < 3; i++) {

puts("waiting ...");

}

return 0;

}

运行结果:

signal.png发生信号时将唤醒由于调用sleep函数而进入阻塞状态的进程

sigaction函数进行信号处理1

2

3#include

int sigaction (int signo, const struct sigaction *act, struct sigaction *oldact);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值