linux下进程调用,Linux进程相关系统调用(一)

(1)fork和vfork

之前用过fork来创建子进程,知道可以根据返回值来区分父子进程,对于父进程来说,fork的返回值是子进程ID,对于子进程来说返回PID为0.关于这一点,vfork函数与fork函数是相同的。而fork与vfork的区别在于在哪呢?

*********************************************************************************

用fork创建的子进程会复制父进程的资源,而用vfork创建的子进程会与父进程共享地址空间。

*********************************************************************************

下面用函数的执行结果说明一下:

#include

#include

#include

int g_var = 0;

int main (void)

{

int var = 1;

pid_t pid;

printf("Process ID: %ld\n",(long)getpid());

printf("Before execute fork system call, g_val = %d,var = %d.\n",g_var,var);

if((pid = fork())<0)

{

printf("Creat a new process failed.\n");

return 1;

}

else if(pid==0)

{

g_var++;

var++;

printf("Process ID: %ld,g_var = %d,var =%d.\n",(long)getpid(),g_var,var);

_exit(0);

}

printf("Process ID: %ld,g_var = %d,var =%d.\n",(long)getpid(),g_var,var);

return 0;

}

修改以上代码,分别使用fork和vfork,执行结果如下:

--->使用fork

gaolu@gaolu-desktop:~$ gcc -o syst systemcall.c

gaolu@gaolu-desktop:~$

gaolu@gaolu-desktop:~$

gaolu@gaolu-desktop:~$ ./syst

Process ID: 6006

Before execute fork system call, g_val = 0,var = 1.

Process ID: 6007,g_var = 1,var =2.

Process ID: 6006,g_var = 0,var =1.

gaolu@gaolu-desktop:~$

gaolu@gaolu-desktop:~$

--->使用vfork

gaolu@gaolu-desktop:~$

gaolu@gaolu-desktop:~$ gcc -o syst systemcall.c

gaolu@gaolu-desktop:~$ ./syst

Process ID: 5990

Before execute vfork system call, g_val = 0,var = 1.

Process ID: 5991,g_var = 1,var =2.

Process ID: 5990,g_var = 1,var =2.

gaolu@gaolu-desktop:~$

gaolu@gaolu-desktop:~$

gaolu@gaolu-desktop:~$

gaolu@gaolu-desktop:~$

以上结果可以证明:用fork函数创建子进程,子进程中修改变量不会影响父进程中变量的取值;用vfork函数创建子进程,子进程修改变量会导致父进程中对应变量值的改变。

*********************************************************************************

使用fork创建子进程往往不是为了获得完全一样的进程,而是通过exec来执行其他可执行程序,所以完全的复制有些多余,存在一定程度的资源消耗,vfork的出现促进了fork机制的改变,目前linux对fork系统调用的实现采用了写时复制(copy-on-write COW)的方法,只有子进程对内存数据进行写操作时,才会进行资源的复制。COW机制使vfork几乎没有了价值,而且子进程对内存的修改会影响父进程,需要特别注意。

**********************************************************************************

(2)extc函数族

在子进程中用exec执行其他的可执行程序,可以对进程中的代码段、数据段、堆栈段进行替换。主要几个函数有execl,execlp,execle,execv,execve,execvp(函数定义略)等。

exec后面为l,表示该函数可以使用可变参数(个数可变);包含v字符,表示支持使用参数列表;包含p,表示如果给出的程序没有给出所在路径,系统会自动搜索PATH路径(不包含p的必须给出文件所在完整路径)。

下面函数示范了execlp和execvp的使用,后者明显具备更大的灵活性。

#include

#include

int main (int argc,char* argv[])

{

if(argc <2)

{

printf("Usage: %s path.\n",argv[0]);

return 1;

}

execlp("/bin/ls","ls",argv[1],(char*)NULL); //支持变长参数,以NULL结尾

return 0;

}

执行结果:

--->execlp()

gaolu@gaolu-desktop:~$

gaolu@gaolu-desktop:~$ gcc -o syst2 systemcall2.c

gaolu@gaolu-desktop:~$ ./syst2

Usage: ./syst2 path.

gaolu@gaolu-desktop:~$ ./syst2 /home/gaolu

commen files        music

data.dat~        picture

desktop         process.c~

document        program~

etcnetworkinterface       syst

Examples        syst2

fcitx-3.4.2        systemcall2.c

fcitx-install        systemcall2.c~

file.c~         systemcall.c~

fileopera~        test.c~

file_operate.c ~       test.dat~

fork_file.c~        test_folder

gao.lu.c~        test_program

ls~         test_program (copy)

LumaQQ         uid.c~

lumaqq_2005-linux_gtk2_x86_with_jre.tar.gz  uidprint.c~

mnt         video

module

gaolu@gaolu-desktop:~$

gaolu@gaolu-desktop:~$

--->execvp()

#include

#include

int main (int argc,char* argv[])

{

if(argc <2)

{

printf("Usage: %s arg list 1 2 3...\n",argv[0]);

return 1;

}

execvp(argv[1],&argv[1]);

return 0;

}

执行结果:

gaolu@gaolu-desktop:~$ gcc -o syst3 systemcall2.c

gaolu@gaolu-desktop:~$ ./syst3

Usage: ./syst3 arg list 1 2 3...

gaolu@gaolu-desktop:~$

gaolu@gaolu-desktop:~$

gaolu@gaolu-desktop:~$ ./syst3 ls /home/gaolu

commen files        music

data.dat~        picture

desktop         process.c~

document        program~

etcnetworkinterface       syst

Examples        syst2

fcitx-3.4.2        syst3

fcitx-install        systemcall2.c

file.c~         systemcall2.c~

fileopera~        systemcall.c~

file_operate.c ~       test.c~

fork_file.c~        test.dat~

gao.lu.c~        test_folder

ls~         test_program

LumaQQ         test_program (copy)

lumaqq_2005-linux_gtk2_x86_with_jre.tar.gz  uid.c~

mnt         uidprint.c~

module         video

gaolu@gaolu-desktop:~$

(3)exit和_exit

可以将两者用在main函数中替代return,区别是exit和_exit不考虑返回值类型。

exit和_exit之间的区别在于:

*****************************************************************************************

[1] exit是在ANSIC中说明,_exit是在POSIX中说明。

[2] exit终止调用进程,退出之前关闭所有文件,清空标准输入输出缓冲区,并执行在atexit中注册的回调函数;_exit终止调用进程,但是不关闭文件,不清除标准输入输出缓冲区,也不调用回调函数。

因此vfork()创建的子进程可以调用_exit退出,但是不要调用exit()退出。

*****************************************************************************************

举例如下:

#include

#include

#include

void do_at_exit(void)

{

printf("You can see the output when the program teminates.\n");

}

int main ()

{

int flag = 0;

flag = atexit(do_at_exit);

if(flag != 0)

{

printf("Can't set exit function.\n");

return EXIT_FAILURE;

}

exit(EXIT_SUCCESS);

}

执行结果:

将函数修改为_exit()以后执行结果如下:

#include

#include

#include

void do_at_exit(void)

{

printf("You can see the output when the program teminates.\n");

}

int main ()

{

int flag = 0;

flag = atexit(do_at_exit);

if(flag != 0)

{

printf("Can't set exit function.\n");

return EXIT_FAILURE;

}

_exit(EXIT_SUCCESS);

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值