创建进程

创建进程通常有两种方法:调用system和fork. system调用十分简单,但效率不高而且存在一定的安全隐患,一般很少用到。fork调用虽然有些复杂,但它更稳定、高效、安全,因此一般作为创建进程的不二选择。

1.调用system

system是一种创建进程十分方便的方法,在程序中,只需给他传递一个命令行参数即可,类似于将将命令行输入终端,都是在shell中运行。因此,system的调用跟linux系统中/bin/sh连接那个shell有很大的关系。不同的Linux系统可能用不同的shell,就算同样的shell不同版本在一些性能上存在差异。

#include "stdlib.h"

int main()
{
    int ret;
    ret = system("ls -l /");
    return ret;
}
在上面的code中调用system创建一个进程,这个进程中运行了“ls -l /”来打印root下的文件。函数的返回值是执行命令行的退出状态,如果linux系统中的shell不能运行会返回127,如果出错则返回-1.


2.调用fork和exec
在Windows中只调用一个CreateProcess,传递应用程序名和一些参数,就会创建一个独立于父进程的子进程,并且这个子进程运行于任何传递给CreateProcess的程序。但在Linux中没有提供一个这样一劳永逸的函数,
要完成CreateProcess的动作需要分两步:1.调用fork将当前进程做一个copy作为子进程,2.调用exec函数将子进程转到另外一个程序中。
先来看看fork的使用:

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

int main()
{
	pid_t child_pid;
	printf("the main program ID is %d\n",getpid());

	child_pid = fork();
	if(child_pid!=0)
	{
		printf("this is the parent process,with id %d\n",getpid());
		printf("the child's process ID is %d\n",child_pid);
	}
	else
	{
		printf("the fork return value is %d\n",child_pid);
		printf("this is the child process,with id %d\n",getpid());
	}
	return 0;
}

调用fork之后,父进程会copy出一个子进程,之后的代码会被这两个进程同时调用。就好像一个进程进入fork,两个进程从fork中出来。在父进程中fork返回值为子进程的ID,在子进程中fork的返回值为0,因此可以根据fork的返回值区分父、子进程。

fork只是将当前的进程做了一个copy得到子进程,父子进程都运行在同一个程序中并且执行fork之后的程序,要想让子进程转进另外的程序执行不同于父进程的代码,必须调用exec.
exec拥有一个家族函数:在exec函数名中添加v,p,l,e实现不同功能,如:execvp(程序名,和参数列表),程序名是要将子进程转入的程序名称,参数列表是以NULL结尾的string 数组
exec家族中字符的含义:
p:传递一个程序名,会在当前目录下查询该程序。如果没有p则需要传递程序的完整路径。
v:接受参数列表,参数列表是以NULL结尾的string 数组。和main(argc,argv)中的argv一样,argv[0]是程序名
l:接受参数列表,这个和v不同,它接受可变参数列表
e:接受额外的参数列表,用来包含环境变量参数,参数列表也是以NULL结尾的string 数组,每个环境变量参数格式如:“VARIABLE=value”

exec会将copy出的子进程转入另外一个program中,因此不会返回,除非发成错误。

用fork和exec生成一个进程,并且用ls程序显示root目录下的文件名:

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

int spawn (char* program, char** arg_list)
{
	pid_t child_pid;
	child_pid = fork ();
	if (child_pid != 0)
	{
		printf("This is the parent process.\n" );
		return child_pid;
	}
	else {
		printf("This is the child process.\n" );
		execvp (program, arg_list);
		fprintf (stderr, “an error occurred in execvp\n”);
		abort ();
	}
}
int main ()
{
	/* The argument list to pass to the “ls” command. */
	char* arg_list[] = {
	“ls”, /* argv[0], the name of the program. */
	“-l”,
	“/”,
	NULL /* The argument list must end with a NULL. */
	};

	spawn (“ls”, arg_list);
	printf (“done with main program\n”);
	return 0;
}

这里用调用ls不是在shell中,而是将生成的子进程转入ls,相当于执行ls程序
进入子进程时,调用execvp如果不发生错误会一直阻塞下去不会返回。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值