Tod*_*lin 103
fork()是如何在Unix中创建新进程的.当您调用时fork,您将创建自己的进程的副本,该进程具有自己的地址空间.这允许多个任务彼此独立地运行,就好像它们各自拥有机器的全部内存一样.
以下是一些示例用法fork:
fork从命令行运行您调用的程序.fork,以创建多个服务器进程,每个处理在自己的地址空间的请求.如果一个人死亡或泄漏内存,其他人不受影响,因此它可以作为容错机制.fork在单独的流程中处理每个页面.这将阻止一个页面上的客户端代码将整个浏览器关闭.fork用于在某些并行程序中生成进程(如使用MPI编写的程序).请注意,这与使用线程不同,线程没有自己的地址空间并且存在于进程中.fork间接使用来启动子进程.例如,每次使用subprocess.PopenPython中的命令时,您都会fork处理子进程并读取其输出.这使程序可以一起工作.forkshell中的典型用法可能如下所示:
int child_process_id = fork();
if (child_process_id) {
// Fork returns a valid pid in the parent process. Parent executes this.
// wait for the child process to complete
waitpid(child_process_id, ...); // omitted extra args for brevity
// child process finished!
} else {
// Fork returns 0 in the child process. Child executes this.
// new argv array for the child process
const char *argv[] = {"arg1", "arg2", "arg3", NULL};
// now start executing some other program
exec("/path/to/a/program", argv);
}
Run Code Online (Sandbox Code Playgroud)
shell生成子进程exec并等待它完成,然后继续自己的执行.请注意,您不必以这种方式使用fork.您可以像并行程序那样生成许多子进程,并且每个进程可以同时运行程序.基本上,无论何时在Unix系统中创建新进程,您都在使用fork().对于Windows等效,请看一下CreateProcess.
如果你想要更多的例子和更长的解释,维基百科有一个不错的总结.而且这里有一些幻灯片这里如何进程,线程和并发在现代操作系统的工作.
Dan*_*ral 13
fork()是Unix如何创建新进程的.在您调用fork()时,将克隆您的进程,并从那里继续执行两个不同的进程.其中一个,孩子,将fork()返回0.另一个,父,将fork()返回子的PID(进程ID).
例如,如果在shell中键入以下内容,shell程序将调用fork(),然后执行您在子项中传递的命令(在本例中为telnetd),同时父项将再次显示提示,作为指示后台进程的PID的消息.
$ telnetd &
Run Code Online (Sandbox Code Playgroud)
至于创建新流程的原因,这就是您的操作系统可以同时执行许多操作的方式.这就是为什么你可以运行一个程序,并在它运行时切换到另一个窗口并执行其他操作.
fork()用于创建子进程.当调用fork()函数时,将生成一个新进程,fork()函数调用将为子进程和父进程返回不同的值.
如果返回值为0,则表示您是子进程,如果返回值是数字(恰好是子进程ID),则表示您是父进程.(如果它是负数,则fork失败并且没有创建子进程)
http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html
fork()将创建一个与父级相同的新子进程.因此,在此之后您在代码中运行的所有内容都将由两个进程运行 - 如果您具有例如服务器,并且您想要处理多个请求,则非常有用.
fork()主要用于为调用此函数的进程创建子进程.无论何时调用fork(),它都会为子id返回零.
pid=fork()
if pid==0
//this is the child process
else if pid!=0
//this is the parent process
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您可以为父级和子级提供不同的操作,并使用多线程功能.
系统调用 fork() 用于创建进程。它不接受任何参数并返回一个进程 ID。fork() 的目的是创建一个新进程,它成为调用者的子进程。创建新的子进程后,两个进程都将执行 fork() 系统调用之后的下一条指令。因此,我们必须区分父和子。这可以通过测试 fork() 的返回值来完成:
如果 fork() 返回负值,则子进程创建失败。fork() 向新创建的子进程返回零。fork() 向父进程返回一个正值,即子进程的进程 ID。返回的进程 ID 是 sys/types.h 中定义的 pid_t 类型。通常,进程 ID 是一个整数。此外,进程可以使用函数 getpid() 来检索分配给该进程的进程 ID。因此,在系统调用 fork() 之后,一个简单的测试就可以判断哪个进程是子进程。请注意,Unix 将制作父地址空间的精确副本并将其提供给子进程。因此,父进程和子进程具有独立的地址空间。
让我们通过一个例子来理解它,以清楚地说明上述几点。此示例不区分父进程和子进程。
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#define MAX_COUNT 200
#define BUF_SIZE 100
void main(void)
{
pid_t pid;
int i;
char buf[BUF_SIZE];
fork();
pid = getpid();
for (i = 1; i <= MAX_COUNT; i++) {
sprintf(buf, "This line is from pid %d, value = %d\n", pid, i);
write(1, buf, strlen(buf));
}
}
Run Code Online (Sandbox Code Playgroud)
假设上述程序执行到调用 fork() 为止。
如果对 fork() 的调用成功执行,Unix 将制作两份相同的地址空间副本,一份用于父级,另一份用于子级。两个进程都将在 fork() 调用之后的下一条语句开始执行。在这种情况下,两个进程都将在分配处开始执行
pid = .....;
Run Code Online (Sandbox Code Playgroud)
两个进程都在系统调用 fork() 之后立即开始执行。由于两个进程具有相同但独立的地址空间,因此在 fork() 调用之前初始化的那些变量在两个地址空间中具有相同的值。由于每个进程都有自己的地址空间,因此任何修改都将独立于其他进程。换句话说,如果父进程改变了其变量的值,那么修改只会影响父进程地址空间中的变量。由 fork() 调用创建的其他地址空间不会受到影响,即使它们具有相同的变量名称。
使用 write 而不是 printf 的原因是什么?这是因为 printf() 是“缓冲的”,这意味着 printf() 会将进程的输出组合在一起。在为父进程缓冲输出的同时,子进程也可能使用 printf 打印出一些信息,这些信息也会被缓冲。因此,由于输出不会立即发送到屏幕,您可能无法获得预期结果的正确顺序。更糟糕的是,这两个进程的输出可能以奇怪的方式混合在一起。为了克服这个问题,您可以考虑使用“无缓冲”写入。
如果您运行此程序,您可能会在屏幕上看到以下内容:
................
This line is from pid 3456, value 13
This line is from pid 3456, value 14
................
This line is from pid 3456, value 20
This line is from pid 4617, value 100
This line is from pid 4617, value 101
................
This line is from pid 3456, value 21
This line is from pid 3456, value 22
................
Run Code Online (Sandbox Code Playgroud)
进程 ID 3456 可能是分配给父进程或子进程的进程 ID。由于这些进程同时运行,它们的输出行以一种相当不可预测的方式混合在一起。此外,这些行的顺序由 CPU 调度程序确定。因此,如果您再次运行此程序,您可能会得到完全不同的结果。
如果您正在编写应用程序,您可能不需要在日常编程中使用 fork。
即使您确实希望程序启动另一个程序来执行某些任务,也有其他更简单的接口在幕后使用 fork,例如 C 和 perl 中的“system”。
例如,如果您希望应用程序启动另一个程序(例如 bc)来为您执行一些计算,则可以使用“system”来运行它。系统执行“fork”来创建一个新进程,然后执行“exec”将该进程转换为 bc。一旦 bc 完成,系统将控制权返回给您的程序。
您还可以异步运行其他程序,但我不记得如何操作。
如果您正在编写服务器、shell、病毒或操作系统,您更有可能想要使用 fork。