Linux程序设计-3.进程控制

3. 进程控制

3.1 环境变量

3.1.1 获取环境变量getenv()

帮助手册:man 3 getenv
包含头文件:

  • `#include <stdlib.h>

函数原型:
char *getenv(const char *name);

参数说明
name环境变量
return成功:环境变量的值
失败:NULL

3.1.2 修改或添加环境变量setenv()

帮助手册:man 3 setenv
包含头文件:

  • `#include <stdlib.h>

函数原型:
int unsetenv(const char *name);

参数说明
name环境变量名
value变量值
overwrite当环境变量存在时
0:不重写
非0:重写
return成功:0
失败:-1,并设置errno

3.1.3 删除环境变量unsetenv()

帮助手册:man 3 unsetenv
包含头文件:

  • `#include <stdlib.h>

函数原型:
char *getenv(const char *name);

参数说明
name环境变量名
return成功:0
失败:-1,并设置errno

3.2创建子进程fork()

帮助手册:man 2 fork
包含头文件:

  • #include <sys/types.h>
  • #include <unistd.h>

函数原型:
pid_t fork(void);

fork()后:

  • 父子进程相同处:
    – 全局变量,data, text, 栈,堆,环境变量,用户ID,宿主目录,进程工作目录,信号处理方式…
  • 父子进程不相同处:
    – 进程ID, fork返回值,父进程ID, 进程运行时间,闹钟(定时器),未决信号集

注:父子进程间数据读时共享,写时复制,父子进程不共享全局变量

参数说明
return成功:子进程:0;父进程:子进程PID
失败:-1,并设置errno

3.3 获得当前进程PIDgetpid()

帮助手册:man 2 getpid
包含头文件:

  • #include <sys/types.h>
  • #include <unistd.h>

函数原型:
pid_t getpid(void)

参数说明
return返回当前进程的PID

3.4 获得父进程PIDgetppid()

帮助手册:man 2 getppid
包含头文件:

  • #include <sys/types.h>
  • #include <unistd.h>

函数原型:
pid_t getppid(void)

参数说明
return返回父进程的PID

示例:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
	printf("Begin...\n");
	pid_t pid = fork();
	if(pid < 0)
	{
		perror("fork error:");
		return -1;
	}
	if(pid == 0)
		printf("This is child process, PID = %d, PPID = %d\n", getpid(), getppid());
	if(pid > 0)
		printf("This is parent process, pid = %d, PID = %d, PPID = %d\n", pid, getpid(), getppid());
	printf("End...\n");
	return 0;
}

3.5 执行一个文件

3.5.1 execl()

帮助手册:man 2 execl
包含头文件:

  • #include <unistd.h>

函数原型:
int execl(const char *pathname, const char *arg, ... /* (char *) NULL */);

参数说明
pathname可执行文件路径
arg参数(注:arg[0]需要用可执行文件占位,最后需要用NULL标识
return成功:不返回
失败:-1,并设置errno

3.5.2 execlp()

帮助手册:man 2 execlp
包含头文件:

  • #include <unistd.h>

函数原型:
int execlp(const char *file, const char *arg, ... /* (char *) NULL */);

函数说明:

  • 执行程序时,使用PATH环境变量,执行的程序可以不用加路径
参数说明
file可执行文件路径
arg参数(注:arg[0]需要用可执行文件占位,最后需要用NULL标识
return成功:不返回
失败:-1,并设置errno

注:execl()execlp()会将原来的代码断进行替换

#include <stdio.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
	execlp("ls", "ls", "-l", NULL);
	perror("execlp error:");
	return 0;
}

3.6 等待子进程中断或结束

  • 孤儿进程:父进程运行结束,子进程被init进程领养。
  • 僵尸进程:子进程运行结束,父进程没有回收子进程资源(PCB)

孤儿进程示例:

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

int main(int argc, char* argv[])
{
	pid_t pid = fork();
	if(pid == 0)
	{
		while(1)
		{
			printf("child process...ppid=%d\n", getppid());
			sleep(1);
		}
	}
	if(pid > 0)
	{
		sleep(3);
		printf("The parent process is finished...\n");
	}
	return 0;
}

僵尸进程示例:

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

int main(int argc, char* argv[])
{
	pid_t pid = fork();
	if(pid == 0)
	{
		sleep(1);
		printf("The child process is finished...\n");
	}
	if(pid > 0)
	{
		while(1)
		{
			printf("parent process...\n");
			sleep(1);
		}

	}
	return 0;
}

3.6.1wait()

帮助手册:man 2 wait
包含头文件:

  • #include <sys/types.h>
  • #include <sys/wait.h>

函数原型:
pid_t wait(int *wstatus);

函数说明:

  • wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值,并回收子进程的PCB。子进程的结束状态值会由参数wstatus返回,而子进程的进程识别码也会一块返回。如果不在意结束状态值,则参数wstatus可以设为NULL。子进程的结束状态值参考waitpid()
参数说明
wstatus传出参数(子进程的死亡原因)
return成功:子进程PID
失败:-1,并设置errno

子进程的死亡原因:

示例:

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

int main(int argc, char* argv[])
{
	pid_t pid = fork();
	if(pid == 0)
	{
		sleep(2);
		printf("The child process is finished...\n");
	}
	if(pid > 0)
	{
		printf("wait...\n");
		pid_t wpid = wait(NULL);
		printf("The child process was dead. wpid = %d, pid = %d\n", wpid, pid);
		while(1) sleep(1);
	}
	return 0;
}

3.6.2 waitpid()

帮助手册:man 2 waitpid
包含头文件:

  • #include <sys/types.h>
  • #include <sys/wait.h>

函数原型:
pid_t waitpid(pid_t pid, int *wstatus, int options);

参数说明
pidpid<-1:等待进程组识别码为pid绝对值的任何子进程
pid=-1:等待任何子进程,相当于wait()
pid=0:等待进程组识别码与目前进程相同的任何子进程
pid>0:等待任何子进程识别码为pid的子进程
optionsNULL:与wait()相同,一会阻塞
WNOHANG:如果没有子进程存在立即返回
WUNTRACED:如果子进程进入暂停状态立马返回,但结束状态不予理会
WCONTINUED:如果通过SIGCONT恢复了停止的子进程,也返回
return成功:子进程PID(如果设置了WNOHANG,如果没有子进程退出返回0)
失败:-1,并设置errno

如果wstatus不为NULLwait()waitpid()将状态信息存储在*wstatus中。可以使用以下宏检查此整数:

说明
WIFEXITED(wstatus)如果子进程正常退出放回真
WEXITSTATUS(wstatus)返回子进程的退出状态(注:WIFEXITED返回真可以使用)
WIFSIGNALED(wstatus)如果子进程被一个信号杀死返回真
WTERMSIG(wstatus)返回杀死子进程的信号(注:WIFSIGNALED返回真可以使用)
WCOREDUMP(wstatus)如果子进程核转储返回真(注:WIFSIGNALED返回真可以使用)
WIFSTOPPED(wstatus)如果子进程处于暂停状态返回真(注:WIFSIGNALED返回真可以使用)
WSTOPSIG(wstatus)返回引发子进程暂停的信号代码(注:WIFSIGNALED返回真可以使用)
WIFCONTINUED(wstatus)如果子进程回复继续运行返回真

示例:

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

int main(int argc, char* argv[])
{
	pid_t pid = fork();
	if(pid == 0)
	{
		printf("\tChild dead.\n");
		sleep(2);
		return 1;
	}
	if(pid > 0)
	{
		printf("wait for child die!\n");
		int status;
		pid_t wpid = wait(NULL);
		printf("wait ok, wpid = %d, pid = %d\n", wpid, 		pid);
		if(WIFEXITED(status))
		{
			printf("child exit with %d\n", 	WEXITSTATUS(status));
		}
		if(WIFSIGNALED(status))
		{
			printf("child killed by %d\n", WTERMSIG(status));
		}
		while(1)
		{
			sleep(1);
		}
	}
	return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char* argv[])
{
    pid_t pid = fork();
    if(pid == 0)
    {
        printf("\tChild dead. pid = %d\n", getpid());
        sleep(2);
        return 1;
    }
    if(pid > 0)
    {
        printf("wait for child die!\n");
        int ret;
        while((ret = waitpid(-1, NULL, WNOHANG)) == 0);
        printf("ret = %d\n", ret);
        while(1)
        {
            sleep(1);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT灰猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值