Linux系统编程之进程

一、Linux进程

程序:死的。只占用磁盘空间。		——剧本。

进程;活的。运行起来的程序。占用内存、cpu等系统资源。	——戏。

PCB进程控制块:

进程id

文件描述符表

进程状态:初始态、就绪态、运行态、挂起态、终止态。

进程工作目录位置

*umask掩码 

信号相关信息资源。

用户id和组id

二、fork函数

fork函数:

pid_t fork(void)

创建子进程。父子进程各自返回。父进程返回子进程pid。子进程返回 0。
getpid();  获取当前进程id。
getppid(); 获取当前进程的父进程id。

循环创建N个子进程模型:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

int main(int argc, char *argv[])
{
    int i;
    pid_t pid;

    for (i = 0; i < 5; i++) {       
        if (fork() == 0)        // 循环期间, 子进程不 fork
            break;
    }
    if (5 == i) {       // 父进程, 从 表达式 2 跳出
        sleep(5);
        printf("I'm parent \n");
    } else {            // 子进程, 从 break 跳出
        sleep(i);
        printf("I'm %dth child\n", i+1);
    }

    return 0;
}

父子进程相同:

刚fork后。data段、text段、堆、栈、环境变量、全局变量、宿主目录位置、进程工作目录位置、信号处理方式。

父子进程不同:

进程id、返回值、各自的父进程、进程创建时间、闹钟、未决信号集。

父子进程共享:

读时共享、写时复制。———————— 全局变量。

1. 文件描述符 2. mmap映射区。

三、exec函数族

使进程执行某一程序。成功无返回值,失败返回 -1。

int execlp(const char *file, const char *arg, ...);	借助 PATH 环境变量找寻待执行程序

	参1: 程序名

	参2: argv0

	参3: argv1

	...: argvN

	哨兵:NULL

int execl(const char *path, const char *arg, ...);	自己指定待执行程序路径。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(void)
{
    pid_t pid;
    pid = fork();
    if (pid == -1 ) {
        perror("fork");
        exit(1);
    } else if (pid > 0) {
        printf("I'm parent pid = %d, parentID = %d\n", getpid(), getppid());
    } else if (pid == 0) {
        sleep(3);
        printf("i am child\n");
        execl("/bin/ls", "ls", "-l",  NULL);
        perror("exec");
        exit(1);
    }
    printf("-------finish...%d\n", getpid());
    return 0;
}

四、僵尸进程和孤儿进程

孤儿进程:

父进程先于子进终止,子进程沦为“孤儿进程”,会被 init 进程领养。

僵尸进程:

子进程终止,父进程尚未对子进程进行回收,在此期间,子进程为“僵尸进程”。 kill 对其无效。

五、进程回收

5.1 wait函数

wait函数:回收子进程退出资源, 阻塞回收任意一个。

pid_t wait(int *status)

参数:(传出) 回收进程的状态。

返回值:成功: 回收进程的pid

	   失败: -1, errno

函数作用1:	阻塞等待子进程退出

函数作用2:	清理子进程残留在内核的 pcb 资源

函数作用3:	通过传出参数,得到子进程结束状态


获取子进程正常终止值:

	WIFEXITED(status) --》 为真 --》调用 WEXITSTATUS(status) --》 得到 子进程 退出值。

获取导致子进程异常终止信号:

	WIFSIGNALED(status) --》 为真 --》调用 WTERMSIG(status) --》 得到 导致子进程异常终止的信号编号。

示例程序:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>

int main(void)
{
	pid_t pid, wpid;
	int status;

	pid = fork();

	if(pid == -1){
		perror("fork error");
		exit(1);
	} else if(pid == 0){		//son
		printf("I'm process child, pid = %d\n", getpid());
		sleep(1);				
		exit(10);
	} else {
		wpid = wait(&status);	//传出参数

		if(WIFEXITED(status)){	//正常退出
			printf("I'm parent, The child process "
					"%d exit normally\n", wpid);
			printf("return value:%d\n", WEXITSTATUS(status));

		} else if (WIFSIGNALED(status)) {	//异常退出
			printf("The child process exit abnormally, "
					"killed by signal %d\n", WTERMSIG(status));
										    //获取信号编号
		} else {
			printf("other...\n");
		}
	}

	return 0;
}

5.2 waitpid函数

waitpid函数:指定某一个进程进行回收。可以设置非阻塞。waitpid(-1, &status, 0) == wait(&status);

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

参数:
	pid:指定回收某一个子进程pid

		> 0: 待回收的子进程pid

		-1:任意子进程

		 0:同组的子进程。

	status:(传出) 回收进程的状态。

	options:WNOHANG 指定回收方式为,非阻塞。

返回值:

	> 0 : 表成功回收的子进程 pid

	 0 : 函数调用时, 参3 指定了WNOHANG, 并且,没有子进程结束。

	-1: 失败。errno

示例程序:

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    pid_t pid;
    pid = fork();

    if (pid < 0) {
        perror("fork failed");
        exit(1);
    }

    if (pid == 0) {
        int i;
        for (i = 3; i > 0; i--) {
            printf("This is the child\n");
            sleep(1);
        }
        exit(34);
    } else {
        int stat_val;
        waitpid(pid, &stat_val, 0);     //阻塞

        if (WIFEXITED(stat_val))
            printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
        else if (WIFSIGNALED(stat_val))
            printf("Child terminated abnormally, signal %d\n", WTERMSIG(stat_val));
    }
    return 0;
}

总结:

wait、waitpid	一次调用,回收一个子进程。

想回收多个。while 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值