What is linux fork

What is linux fork

Для порождения процессов в ОС Linux существует два способа. Один из них позволяет полностью заменить другой процесс, без замены среды выполнения. Другим способом можно создать новый процесс с помощью системного вызова fork() . Синтаксис вызова следующий:

pid_t является примитивным типом данных, который определяет идентификатор процесса или группы процессов. При вызове fork() порождается новый процесс (процесс-потомок), который почти идентичен порождающему процессу-родителю. Процесс-потомок наследует следующие признаки родителя:

  • сегменты кода, данных и стека программы;
  • таблицу файлов, в которой находятся состояния флагов дескрипторов файла, указывающие, читается ли файл или пишется. Кроме того, в таблице файлов содержится текущая позиция указателя записи-чтения;
  • рабочий и корневой каталоги;
  • реальный и эффективный номер пользователя и номер группы;
  • приоритеты процесса (администратор может изменить их через nice );
  • контрольный терминал;
  • маску сигналов;
  • ограничения по ресурсам;
  • сведения о среде выполнения;
  • разделяемые сегменты памяти.

Потомок не наследует от родителя следующих признаков:

  • идентификатора процесса (PID, PPID);
  • израсходованного времени ЦП (оно обнуляется);
  • сигналов процесса-родителя, требующих ответа;
  • блокированных файлов (record locking).

При вызове fork() возникают два полностью идентичных процесса. Весь код после fork() выполняется дважды, как в процессе-потомке, так и в процессе-родителе.

Процесс-потомок и процесс-родитель получают разные коды возврата после вызова fork() . Процесс-родитель получает идентификатор (PID) потомка. Если это значение будет отрицательным, следовательно при порождении процесса произошла ошибка. Процесс-потомок получает в качестве кода возврата значение 0, если вызов fork() оказался успешным.

Таким образом, можно проверить, был ли создан новый процесс:

Пример порождения процесса через fork() приведен ниже:

Когда потомок вызывает exit() , код возврата передается родителю, который ожидает его, вызывая wait() . WEXITSTATUS() представляет собой макрос, который получает фактический код возврата потомка из вызова wait() .

Функция wait() ждет завершения первого из всех возможных потомков родительского процесса. Иногда необходимо точно определить, какой из потомков должен завершиться. Для этого используется вызов waitpid() с соответствующим PID потомка в качестве аргумента. Еще один момент, на который следует обратить внимание при анализе примера, это то, что и родитель, и потомок используют переменную rv . Это не означает, что переменная разделена между процессами. Каждый процесс содержит собственные копии всех переменных.

Рассмотрим следующий пример:

В этом случае будет создано семь процессов-потомков. Первый вызов fork() создает первого потомка. Как указано выше, процесс наследует положение указателя команд от родительского процесса. Указатель команд содержит адрес следующего оператора программы. Это значит, что после первого вызова fork() указатель команд и родителя, и потомка находится перед вторым вызовом fork() .После второго вызова fork() и родитель, и первый потомок производят потомков второго поколения — в результате образуется четыре процесса. После третьего вызова fork() каждый процесс производит своего потомка, увеличивая общее число процессов до восьми.

Так называемые процессы-зомби возникают, если потомок завершился, а родительский процесс не вызвал wait() . Для завершения процессов используют либо оператор возврата, либо вызов функции exit() со значением, которое нужно возвратить операционной системе. Операционная система оставляет процесс зарегистрированным в своей внутренней таблице данных, пока родительский процесс не получит кода возврата потомка, либо не закончится сам. В случае процесса-зомби его код возврата не передается родителю, и запись об этом процессе не удаляется из таблицы процессов операционной системы. При дальнейшей работе и появлении новых зомби таблица процессов может быть заполнена, что приведет к невозможности создания новых процессов.

Источник

Learn and use fork(), vfork(), wait() and exec() system calls across Linux Systems

It is found that in any Linux/Unix based Operating Systems it is good to understand fork and vfork system calls, how they behave, how we can use them and differences between them. Along with these wait and exec system calls are used for process spawning and various other related tasks.

Most of these concepts are explained using programming examples. In this article, I will be covering what are fork, vfork, exec and wait system calls, their distinguishing characters and how they can be better used.

fork(): System call to create a child process.

This will yield output mentioning what is fork used for, syntax and along with all the required details.

The syntax used for the fork system call is as below,

Fork system call creates a child that differs from its parent process only in pid(process ID) and ppid(parent process ID). Resource utilization is set to zero. File locks and pending signals are not inherited. (In Linux “fork” is implemented as “copy-on-write()“).

Note:-Copy on write” -> Whenever a fork() system call is called, a copy of all the pages(memory) related to the parent process is created and loaded into a separate memory location by the Operating System for the child process. But this is not needed in all cases and may be required only when some process writes to this address space or memory area, then only separate copy is created/provided.

Return values:- PID (process ID) of the child process is returned in parents thread of execution and “zero” is returned in child’s thread of execution. Following is the c-programming example which explains how fork system call works.

Whenever any system call is made there are plenty of things that take place behind the scene in any unix/linux machines.

First of all context switch happens from user mode to kernel(system) mode. This is based on the process priority and unix/linux operating system that we are using. In the above C example code we are using “<” opening curly brace which is the entry of the context and “>” closing curly brace is for exiting the context. The following table explains context switching very clearly.

vfork()

vfork –> create a child process and block parent process.

Note:- In vfork, signal handlers are inherited but not shared.

This will yield output mentioning what is vfork used for, syntax and along with all the required details.

vfork is as same as fork except that behavior is undefined if process created by vfork either modifies any data other than a variable of type pid_t used to store the return value p of vfork or calls any other function between calling _exit() or one of the exec() family.

Note: vfork is sometimes referred to as special case of clone.

Following is the C programming example for vfork() how it works.

Note: – As explained earlier, many a times the behaviour of the vfork system call is not predictable. As in the above case it had printed before once and after twice but aborted the call with _exit() function. It is better to use fork system call unless otherwise and avoid using vfork as much as possible.

Differences between fork() and vfork()

Vfork() behaviour explained in more details in the below program.

Note: Again if you observe the outcome of vfork is not defined. Value of “n” has been printed first time as 10, which is expected. But the next time in the parent process it has printed some garbage value.

wait() system call suspends execution of current process until a child has exited or until a signal has delivered whose action is to terminate the current process or call signal handler.

There are other system calls related to wait as below,

1) waitpid(): suspends execution of current process until a child as specified by pid arguments has exited or until a signal is delivered.

2) wait3(): Suspends execution of current process until a child has exited or until signal is delivered.

3) wait4(): As same as wait3() but includes pid_t pid value.

exec() family of functions or sys calls replaces current process image with new process image.

There are functions like execl, execlp,execle,execv, execvp and execvpe are used to execute a file.

These functions are combinations of array of pointers to null terminated strings that represent the argument list , this will have path variable with some environment variable combinations.

This function is used for normal process termination. The status of the process is captured for future reference. There are other similar functions exit(3) and _exit()., which are used based on the exiting process that one is interested to use or capture.

Conclusion:-

The combinations of all these system calls/functions are used for process creation, execution and modification. Also these are called “shell” spawning set-of functions. One has to use these functions cautiously keeping in mind the outcome and behaviour.

2 thoughts on “Learn and use fork(), vfork(), wait() and exec() system calls across Linux Systems”

I tried your first example in a virtual terminal in Linux Mint 19 XFCE, and it produced an error:

l_fork.c:3:1: error: unknown type name ‘Int’; did you mean ‘int’?
Int main(void)
^

I corrected the ‘Int’ to ‘int’ and ran it again, and this time it produced a slightly different output to yours:

Before fork
after fork
after fork

Why does it produce two ‘after fork’ lines?

Fork() creates a child process that is why it prints two times, one for the parent and other for the child.
As you can see there is fork() call before the “after fork” print statement.

Источник

What is the meaning of fork() and grep in Linux?

As a non-native English speaker, I have difficulty remembering Linux commands compared to other APIs. In Linux, the function names don’t seem to indicate their purpose.

Why is the name fork() chosen to create a child process? In the dictionary, fork means «a utensil with two or more prongs», which is unrelated to creating a new process.

Why is the name grep chosen to «print lines matching a pattern»? Does grep mean «g report»?

Where can I find the etymology behind other commands in the Linux API?

2 Answers 2

Fork can mean to split in two, as a road (source).

Fork (15): to divide into branches.

From an idiomatic command sequence in the qed and ed text editors: ‘g/re/p’, meaning: globally search for a regular expression and print.

This answer lists the etymology of some Linux commands.

Linux forks, a term often applied to the varieties of Linux distributions, are poorly understood even in the Linux community. Are all the various distributions available on the internet true forks of the kernal? Kevin Morgan argues that they are not. Is his Enterprise OpenSource Magazine (formerly LinuxWorld Magazine) article “Linux Technology Leadership and the Forking Issue”, he explores the concept of forking in detail, explains the advantages of having unique variants for distinct applications and explains why variants are not forks.

Источник

fork(2) — Linux man page

Synopsis

Description

The process attributes in the preceding list are all specified in POSIX.1-2001. The parent and child also differ with respect to the following Linux-specific process attributes: * The child does not inherit directory change notifications (dnotify) from its parent (see the description of F_NOTIFY in fcntl(2)). * The prctl(2) PR_SET_PDEATHSIG setting is reset so that the child does not receive a signal when its parent terminates. * The default timer slack value is set to the parent’s current timer slack value. See the description of PR_SET_TIMERSLACK in prctl(2). * Memory mappings that have been marked with the madvise(2) MADV_DONTFORK flag are not inherited across a fork(). * The termination signal of the child is always SIGCHLD (see clone(2)). * The port access permission bits set by ioperm(2) are not inherited by the child; the child must turn on any bits that it requires using ioperm(2).

Note the following further points: * The child process is created with a single thread—the one that called fork(). The entire virtual address space of the parent is replicated in the child, including the states of mutexes, condition variables, and other pthreads objects; the use of pthread_atfork(3) may be helpful for dealing with problems that this can cause. * The child inherits copies of the parent’s set of open file descriptors. Each file descriptor in the child refers to the same open file description (see open(2)) as the corresponding file descriptor in the parent. This means that the two descriptors share open file status flags, current file offset, and signal-driven I/O attributes (see the description of F_SETOWN and F_SETSIG in fcntl(2)). * The child inherits copies of the parent’s set of open message queue descriptors (see mq_overview(7)). Each descriptor in the child refers to the same open message queue description as the corresponding descriptor in the parent. This means that the two descriptors share the same flags (mq_flags). * The child inherits copies of the parent’s set of open directory streams (see opendir(3)). POSIX.1-2001 says that the corresponding directory streams in the parent and child may share the directory stream positioning; on Linux/glibc they do not.

Return Value

Errors

Conforming to

Notes

Under Linux, fork() is implemented using copy-on-write pages, so the only penalty that it incurs is the time and memory required to duplicate the parent’s page tables, and to create a unique task structure for the child.

Since version 2.3.3, rather than invoking the kernel’s fork() system call, the glibc fork() wrapper that is provided as part of the NPTL threading implementation invokes clone(2) with flags that provide the same effect as the traditional system call. (A call to fork() is equivalent to a call to clone(2) specifying flags as just SIGCHLD.) The glibc wrapper invokes any fork handlers that have been established using pthread_atfork(3).

Источник

Читайте также:  Брандмауэр исключения добавить порт windows 10
Оцените статью