在windows下,创建一个进程可以用CreateProcess,它将启动另一个程序;
而在linux下,创建一个进程可以用fork,顾名思义就是“分叉”,调用fork就像孙悟空叫一声“变”,于是出现了两个孙悟空,而且两个人在当时是完全一样的,他们共享同样的过去,但他们通常应该有不一样的未来,于是两个孙悟空要立即判断出自已是不是变出来的那一个,这就要使用调用fork后的返回值,然后就可以做符合身分的事了。那如果程序只能创建自已的复本,linux不就只能运行一个程序的多个复本吗?还没完呢,通过fork的返回值判断出自已是复本,就可以立即调用某个以exec开头的系统函数执行另一个程序,这个程序将替换自已。
表面上看起来linux下的多进程较之windows下的多进程要复杂一些,要先“分叉”(即fork)再变身(即exec*),这样的两步走肯定是有好处的,只fork不exec*,不就像windows下的多线程了吗?
看看这篇文章: Linux下的多进程编程 ,你就更明白了。
fork演示程序:
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
int main()
{
int i;
std::cout << "before fork." << "/tpid:" << getpid() << std::endl;
if(fork() == 0) //child process
{
std::cout << "child process." << "/tpid:" << getpid() << std::endl;
}
else
{
std::cout << "main process." << "/tpid:" << getpid() << std::endl;
}
std::cout << "end fork." << "/tpid:" << getpid() << std::endl;
return 0;
}
exec*函数可以将调用的进程用新进程替换,以execl为例,做做练习:
[code]
//file: demo_execl.cpp
#include <iostream>
#include <sys/unistd.h>
int main(int argc, char* argv[])
{
if(execl("./print_cmdline.out", "arg0", "arg1", (char*)0) < 0)
{
std::cout << "execl error" << std::endl;
return -1;
}
return 0;
}
[/code]
[code]
//print_cmdline.cpp
#include <iostream>
int main(int argc, char* argv[])
{
for(size_t i = 0; i < argc; ++i)
std::cout << argv[i] << " ";
std::cout << std::endl;
return 0;
}
[/code]
$g++ demo_execl.cpp -o demo_execl.out
$g++ print_cmdline.cpp -o print_cmdline.out
$ ./demo_execl.out
arg0 arg1
哎呀,print_cmdline.out的argv[0]竟然不是"./print_cmdline.out",那怎么在print_cmdline.out获得程序自身的名称啊,我以前一直取用argv[0]的?在linux下你应该这样做:
[code]
//file:getAppPathName.cpp
#include <sys/types.h>
#include <sys/unistd.h>
#include <iostream>
#include <string>
std::string getAppPathName();
int main()
{
std::cout << getAppPathName() << std::endl;
return 0;
}
std::string getAppPathName()
{
char buffer[2048];
int count = readlink( "/proc/self/exe", buffer, sizeof(buffer)/sizeof(buffer[0]) );
assert( count >= 0 && count < sizeof(buffer)/sizeof(buffer[0]) );
buffer[count] = '/0';
return buffer;
}
[/code]
而在linux下,创建一个进程可以用fork,顾名思义就是“分叉”,调用fork就像孙悟空叫一声“变”,于是出现了两个孙悟空,而且两个人在当时是完全一样的,他们共享同样的过去,但他们通常应该有不一样的未来,于是两个孙悟空要立即判断出自已是不是变出来的那一个,这就要使用调用fork后的返回值,然后就可以做符合身分的事了。那如果程序只能创建自已的复本,linux不就只能运行一个程序的多个复本吗?还没完呢,通过fork的返回值判断出自已是复本,就可以立即调用某个以exec开头的系统函数执行另一个程序,这个程序将替换自已。
表面上看起来linux下的多进程较之windows下的多进程要复杂一些,要先“分叉”(即fork)再变身(即exec*),这样的两步走肯定是有好处的,只fork不exec*,不就像windows下的多线程了吗?
看看这篇文章: Linux下的多进程编程 ,你就更明白了。
fork演示程序:
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
int main()
{
int i;
std::cout << "before fork." << "/tpid:" << getpid() << std::endl;
if(fork() == 0) //child process
{
std::cout << "child process." << "/tpid:" << getpid() << std::endl;
}
else
{
std::cout << "main process." << "/tpid:" << getpid() << std::endl;
}
std::cout << "end fork." << "/tpid:" << getpid() << std::endl;
return 0;
}
exec*函数可以将调用的进程用新进程替换,以execl为例,做做练习:
[code]
//file: demo_execl.cpp
#include <iostream>
#include <sys/unistd.h>
int main(int argc, char* argv[])
{
if(execl("./print_cmdline.out", "arg0", "arg1", (char*)0) < 0)
{
std::cout << "execl error" << std::endl;
return -1;
}
return 0;
}
[/code]
[code]
//print_cmdline.cpp
#include <iostream>
int main(int argc, char* argv[])
{
for(size_t i = 0; i < argc; ++i)
std::cout << argv[i] << " ";
std::cout << std::endl;
return 0;
}
[/code]
$g++ demo_execl.cpp -o demo_execl.out
$g++ print_cmdline.cpp -o print_cmdline.out
$ ./demo_execl.out
arg0 arg1
哎呀,print_cmdline.out的argv[0]竟然不是"./print_cmdline.out",那怎么在print_cmdline.out获得程序自身的名称啊,我以前一直取用argv[0]的?在linux下你应该这样做:
[code]
//file:getAppPathName.cpp
#include <sys/types.h>
#include <sys/unistd.h>
#include <iostream>
#include <string>
std::string getAppPathName();
int main()
{
std::cout << getAppPathName() << std::endl;
return 0;
}
std::string getAppPathName()
{
char buffer[2048];
int count = readlink( "/proc/self/exe", buffer, sizeof(buffer)/sizeof(buffer[0]) );
assert( count >= 0 && count < sizeof(buffer)/sizeof(buffer[0]) );
buffer[count] = '/0';
return buffer;
}
[/code]