linux启动新进程



说到进程,首先要明确的一个概念就是什么是进程,进程是“a program in execution”。一个进程由如下元素组成:

–程序的上下文(context),它是程序当前执行的状态

–程序的当前执行目录

–程序访问的文件和目录

–程序的信任状态或者说访问权限,比如它的文件模式和所有权

–内存和其他分配给进程的系统资源

本文讨论创建进程

1、  system库函数

在头文件#include<stdlib.h>中包含

函数原型: int system(const char *command);

功能描述:  system()通过调用/bin/sh –c  command来执行具体的command命令,在command完成后返回。在command执行期间,SIGCHLD信号被阻塞,SIGINTSIGQUIT将被忽略。

返回值:    如果没有找到/bin/shsystem返回127

                            如果出现其他错误则返回-1

                            如果执行成功则返回command的代码。

                            但是如果commandNULLsystem返回一个非0值,否则返回0

示例:\

#include<stdlib.h>

#include<stdio.h>

int main()

{

printf("Running ps with system\n");

system("ps -ax");

//ps命令完成后从system调用中返回,继续执行下一个语句,Done出现在末尾。若改为system("ps -ax &");后台执行ps命令,ps程序一启动shell就返回了。故Done会出现在中间。

printf("Done.\n");

exit(0);

}

 

2、  fork系统调用

fork调用创建一个新的进程。新的进程或者说子进程是调用进程的或者说父进程的副本。

Fork的语法是

#include<unistd.h>

pid_t fork(void);

如果fork执行成功,就向父进程返回子进程的PID,并向子进程返回0。这就一起这即使你只调用fork一次,他也会返回两次。

Fork创建的新进程是和父进程(除了PIDPPID)一样的副本,包括真实和有效的UIDGID、进程组合会话ID、环境、资源限制、打开的文件以及共享内存段。

父进程和子进程之间有一点区别。子进程没有继承父进程的超市设置(使用alarm调用

)父进程创建的文件锁,或者未决信号。要理解的关键概念是fork创建的新进程是父进程的一个准确副本。

 

2fork系统调用

fork调用创建一个新的进程。新的进程或者说子进程是调用进程的或者说父进程的副本。

Fork的语法是

#include<unistd.h>

pid_t fork(void);

如果fork执行成功,就向父进程返回子进程的PID,并向子进程返回0。这就一起这即使你只调用fork一次,他也会返回两次。

Fork创建的新进程是和父进程(除了PIDPPID)一样的副本,包括真实和有效的UIDGID、进程组合会话ID、环境、资源限制、打开的文件以及共享内存段。

父进程和子进程之间有一点区别。子进程没有继承父进程的超时设置(使用alarm调用)父进程创建的文件锁,或者未决信号。要理解的关键概念是fork创建的新进程是父进程的一个准确副本。

示例:

  1. <span style="font-size: 14px;">#include<unistd.h>  
  2. #include<stdio.h>  
  3. #include<stdlib.h>  
  4. #include<string.h>  
  5. int main(void)  
  6. {  
  7.     pid_t child;  
  8.     if((child = fork()) == -1)  
  9.     {  
  10.         perror("fork");  
  11.         exit(EXIT_FAILURE);  
  12.     }  
  13.     else if(child == 0)                 //子进程中  
  14.     {  
  15.         puts("in child");  
  16.         printf("\tchild pid = %d\n",getpid());  
  17.         printf("\tchild ppid = %d\n",getppid());  
  18.         exit(EXIT_SUCCESS);  
  19.     }  
  20.     else      
  21.     {  
  22.         puts("in parent");  
  23.         printf("\tparent pid = %d\n",getpid());  
  24.         printf("\tparent ppid = %d\n",getppid());  
  25.     }  
  26.     exit(EXIT_SUCCESS);  
  27. }  
  28. </span>  
<span style="font-size: 14px;">#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
	pid_t child;
	if((child = fork()) == -1)
	{
		perror("fork");
		exit(EXIT_FAILURE);
	}
	else if(child == 0)					//子进程中
	{
		puts("in child");
		printf("\tchild pid = %d\n",getpid());
		printf("\tchild ppid = %d\n",getppid());
		exit(EXIT_SUCCESS);
	}
	else	
	{
		puts("in parent");
		printf("\tparent pid = %d\n",getpid());
		printf("\tparent ppid = %d\n",getppid());
	}
	exit(EXIT_SUCCESS);
}
</span>


 

3、  exec函数族

fork函数一样,exec也在<unistd.h>中声明。它的原型为:

int execl(const char *path, const char*arg, ...(char *) 0);//以0结尾

int execlp(const char *file, const char*arg, ...(char *) 0);

int execle(const char *path, const char*arg , ...,(char *) 0, char * const envp[]);

int execv(const char *path, char *const argv[]);

int execvp(const char *file, char *const argv[]);

int execve(const char *path, char *const argv[], char *const envp[]);

 

exec用被执行的程序完全替换了调用进程的映像。Fork创建了一个新进程就产生了一个新的PIDexec启动一个新程序,替换原有进程。因此被执行的进程的PID不会改变。

例如:

int execve(const char *path, char *constargv[], char *const envp[]);

接收三个参数:

path是要执行的二进制文件或脚本的完整路径。

argv是要传递给程序的完整参数列表,包括argv[0],它一般是执行程序的名字,

envp是指向用于执行execed程序的专门环境的指针。

这几个函数可以简单讨论如下:

名字中含有l的函数:希望接受以逗号分隔的参数列表,列表以NULL指针作为结束标志,这些参数将传递给被执行的程序。

名字中包v的函数:则接受一个向量,也就是以空结尾的字符串的指针数组。这个数组必须以一个NULL指针作为结束标志。

不过,需要注意的是,有时候可能那个NULL,需要写成(char *)0

  1. <span style="font-size: 14px;">//一个创建num个进程的示例:  
  2. //其中batchscript是已经写好的shell脚本文件。  
  3. void createsubprocess(int num)  
  4. {  
  5.     int i;  
  6.     int child;  
  7.     int pid[num];     
  8.     for(i=0;i<num;i++)  
  9.     {  
  10.         if((child = fork()) == -1)  
  11.         {  
  12.             perror("fork");  
  13.             exit(EXIT_FAILURE);  
  14.         }  
  15.         else if(child==0)       //子进程运行  
  16.         {  
  17.             pid[i]=getpid();  
  18.             if(execl("/usr/audio/./batchscript","./batchscript",(char *)0) == -1 )  
  19.             {  
  20.                 perror("execl");  
  21.                 exit(EXIT_FAILURE);  
  22.             }  
  23.         }  
  24.           
  25.         else  
  26.         {     
  27.         }     
  28.     }  
  29.     for(i=0;i<num;i++)  
  30.     {  
  31.         waitpid(pid[i],NULL,0);  
  32.                   
  33.     }  
  34. }  
  35. </span>  
<span style="font-size: 14px;">//一个创建num个进程的示例:
//其中batchscript是已经写好的shell脚本文件。
void createsubprocess(int num)
{
	int i;
	int child;
	int pid[num];	
	for(i=0;i<num;i++)
	{
		if((child = fork()) == -1)
		{
			perror("fork");
			exit(EXIT_FAILURE);
		}
		else if(child==0)		//子进程运行
		{
			pid[i]=getpid();
			if(execl("/usr/audio/./batchscript","./batchscript",(char *)0) == -1 )
			{
				perror("execl");
				exit(EXIT_FAILURE);
			}
		}
		
		else
		{	
		}   
	}
	for(i=0;i<num;i++)
	{
		waitpid(pid[i],NULL,0);
				
	}
}
</span>


实现了多进程并发。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值