This shows you the differences between two versions of the page.
os_cp:fork_exec_pipes [2024/05/08 13:31] jkonczak utworzono |
os_cp:fork_exec_pipes [2025/05/19 22:27] (current) jkonczak |
||
---|---|---|---|
Line 5: | Line 5: | ||
To create a new process, POSIX defines the ''fork'' function: | To create a new process, POSIX defines the ''fork'' function: | ||
<html><span style="float:right"><small>Needs header:<code>unistd.h</code></small></span> | <html><span style="float:right"><small>Needs header:<code>unistd.h</code></small></span> | ||
- | <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html"></html> | + | <a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/fork.html"></html> |
''pid_t **fork**()'' | ''pid_t **fork**()'' | ||
<html></a></html> | <html></a></html> | ||
Line 14: | Line 14: | ||
\\ | \\ | ||
**Upon success, ''fork'' returns the pid of the child process in the parent | **Upon success, ''fork'' returns the pid of the child process in the parent | ||
- | process, and the value of ''0'' in the the child process.** | + | process, and the value of ''0'' in the child process.** |
\\ | \\ | ||
Fork may fail if the resource limits are exhausted, and in such case the | Fork may fail if the resource limits are exhausted, and in such case the | ||
Line 33: | Line 33: | ||
To learn its own process identifier, the process can execute | To learn its own process identifier, the process can execute | ||
<html><span style="float:right"><small>Needs header: <code>unistd.h</code></small></span> | <html><span style="float:right"><small>Needs header: <code>unistd.h</code></small></span> | ||
- | <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html"></html> | + | <a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/getpid.html"></html> |
''pid_t **getpid**()'' | ''pid_t **getpid**()'' | ||
<html></a></html> | <html></a></html> | ||
Line 39: | Line 39: | ||
To learn the process identifier of its parent, the process can execute | To learn the process identifier of its parent, the process can execute | ||
<html><span style="float:right"><small>Needs header: <code>unistd.h</code></small></span> | <html><span style="float:right"><small>Needs header: <code>unistd.h</code></small></span> | ||
- | <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html"></html> | + | <a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/getppid.html"></html> |
''pid_t **getppid**()'' | ''pid_t **getppid**()'' | ||
<html></a></html> | <html></a></html> | ||
Line 57: | Line 57: | ||
\\ | \\ | ||
<html><span style="float:right"><small>Needs header:<br><code>sys/wait.h</code></small></span> | <html><span style="float:right"><small>Needs header:<br><code>sys/wait.h</code></small></span> | ||
- | <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html"></html> | + | <a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/wait.html"></html> |
''pid_t **wait**(int *//stat_loc//)'' \\ | ''pid_t **wait**(int *//stat_loc//)'' \\ | ||
''pid_t **waitpid**(pid_t //pid//, int *//stat_loc//, int //options//)'' | ''pid_t **waitpid**(pid_t //pid//, int *//stat_loc//, int //options//)'' | ||
Line 91: | Line 91: | ||
\\ | \\ | ||
Run the program and observe it in a live process viewer. \\ | Run the program and observe it in a live process viewer. \\ | ||
- | <small> <html><a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/sleep.html"></html> | + | <small> <html><a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/sleep.html"></html> |
''sleep(int //sec//)''<html></a></html> sleeps with second resolution. (The other POSIX sleep function is | ''sleep(int //sec//)''<html></a></html> sleeps with second resolution. (The other POSIX sleep function is | ||
- | ''[[https://pubs.opengroup.org/onlinepubs/9699919799/functions/nanosleep.html|nanosleep]]''; | + | ''[[https://pubs.opengroup.org/onlinepubs/9799919799/functions/nanosleep.html|nanosleep]]''; |
C standard includes now the equivalent ''[[https://en.cppreference.com/w/c/thread/thrd_sleep|thrd_sleep]]'') | C standard includes now the equivalent ''[[https://en.cppreference.com/w/c/thread/thrd_sleep|thrd_sleep]]'') | ||
\\ | \\ | ||
Line 117: | Line 117: | ||
So, typically to start a new process, one has to ''fork'' and then ''exec…'' in the child: | So, typically to start a new process, one has to ''fork'' and then ''exec…'' in the child: | ||
<html><div style="width: fit-content"><pre style="line-height: 1"> | <html><div style="width: fit-content"><pre style="line-height: 1"> | ||
- | prog1 ,------. | + | prog1 ,------. <span style="color:#aaa">prog1</span> |
- | -------------------| fork |-------------------------------------- | + | -------------------| fork |-------------------------------------------------- |
- | pid: x (ppid: y) `------\ | + | pid: x (ppid: y) `------\ <span style="color:#aaa">pid: x (ppid: y)</span> |
- | \ prog1 ,-------. prog2 | + | \ |
- | `-------------------| exec… |-------- | + | \ prog1 ,-------. prog2 |
- | pid: z (ppid: x) `-------' | + | `-------------------| exec… |------------------- |
+ | pid: z (ppid: x) `-------' <span style="color:#aaa">pid: z (ppid: x)</span> | ||
</pre></div></html> | </pre></div></html> | ||
To this end, a family of functions starting with ''exec'' is provided: \\ | To this end, a family of functions starting with ''exec'' is provided: \\ | ||
<html><span style="float:right"><small>Needs header:<br><code>unistd.h</code></small></span> | <html><span style="float:right"><small>Needs header:<br><code>unistd.h</code></small></span> | ||
- | <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/execve.html"></html> | + | <a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/execve.html"></html> |
''int **execlp**(const char *//file//, const char *arg0, ... /*, (char *)**0** */)'' \\ | ''int **execlp**(const char *//file//, const char *arg0, ... /*, (char *)**0** */)'' \\ | ||
''int **execl **(const char *//path//, const char *arg0, ... /*, (char *)**0** */)'' \\ | ''int **execl **(const char *//path//, const char *arg0, ... /*, (char *)**0** */)'' \\ | ||
- | ''int **execle**(const char *//path//, const char *arg0, ... /*, (char *)**0**,*/ char *const //envp//[])'' \\ | + | ''int **execle**(const char *//path//, const char *arg0, ... /*, (char *)**0**, char *const //envp//[]*/)'' \\ |
''int **execvp**(const char *//file//, char *const //argv//[])'' \\ | ''int **execvp**(const char *//file//, char *const //argv//[])'' \\ | ||
''int **execv **(const char *//path//, char *const //argv//[])'' \\ | ''int **execv **(const char *//path//, char *const //argv//[])'' \\ | ||
Line 144: | Line 145: | ||
following ''exec…'' do execute, then ''exec…'' must have failed. | following ''exec…'' do execute, then ''exec…'' must have failed. | ||
- | Importantly, upon executing ''exec…'' the list of open files is retained. | + | Importantly, upon executing ''exec…'' the list of open files is retained((With |
+ | the exception of files on which the programmer explicitly set the //close-on-exec// | ||
+ | flag for the file descriptor, for instance by passing ''O_CLOEXEC'' among the flags | ||
+ | upon opening the file or by issuing a ''fcntl(…, F_SETFD, FD_CLOEXEC|…)'' for the | ||
+ | file.)). | ||
\\ | \\ | ||
Almost all resources are released. See the documentation for other exceptions. | Almost all resources are released. See the documentation for other exceptions. | ||
Line 157: | Line 162: | ||
char arg0[] = "ls"; char arg2[] = "-a"; | char arg0[] = "ls"; char arg2[] = "-a"; | ||
char arg1[] = "-l"; char arg3[] = "/tmp"; | char arg1[] = "-l"; char arg3[] = "/tmp"; | ||
+ | char *argv[] = {arg0, arg1, arg2, arg3, NULL}; | ||
# Argument list: | # Argument list: | ||
execlp("ls", arg0, arg1, arg2, arg3, NULL); | execlp("ls", arg0, arg1, arg2, arg3, NULL); | ||
# Argument vector: | # Argument vector: | ||
- | char *argv[] = {arg0, arg1, arg2, arg3, NULL}; | ||
execvp("ls", argv); | execvp("ls", argv); | ||
</code> | </code> | ||
Line 192: | Line 197: | ||
<small>To access an unprocessed array of environment variables for the current process, | <small>To access an unprocessed array of environment variables for the current process, | ||
one must have in the source code the following lines: | one must have in the source code the following lines: | ||
+ | <html><div style="margin-top:-1.4em"></div></html> | ||
<code c> | <code c> | ||
#include <unistd.h> | #include <unistd.h> | ||
Line 200: | Line 206: | ||
(Normally, to access such variables of the running process one shall use the | (Normally, to access such variables of the running process one shall use the | ||
''[[https://en.cppreference.com/w/cpp/utility/program/getenv|getenv]]'' and | ''[[https://en.cppreference.com/w/cpp/utility/program/getenv|getenv]]'' and | ||
- | ''[[https://pubs.opengroup.org/onlinepubs/9699919799/functions/setenv.html|setenv]]'' | + | ''[[https://pubs.opengroup.org/onlinepubs/9799919799/functions/setenv.html|setenv]]'' |
functions. \\ | functions. \\ | ||
<small> The ''environ'' variable is useful when one wants to pass a slightly | <small> The ''environ'' variable is useful when one wants to pass a slightly | ||
Line 217: | Line 223: | ||
<small> | <small> | ||
To measure time, you can use the following C11 code: | To measure time, you can use the following C11 code: | ||
+ | <HTML><div style="margin-top:-1.4em;line-height:100%"></HTML> | ||
<code c> | <code c> | ||
#include <time.h> | #include <time.h> | ||
Line 226: | Line 233: | ||
double elapsedSec = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9; | double elapsedSec = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9; | ||
</code> | </code> | ||
+ | <HTML></div></HTML> | ||
</small> | </small> | ||
Line 239: | Line 247: | ||
POSIX defines the following functions: \\ | POSIX defines the following functions: \\ | ||
<html><span style="float:right"><small>Needs header:<br><code>unistd.h</code></small></span> | <html><span style="float:right"><small>Needs header:<br><code>unistd.h</code></small></span> | ||
- | <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html"></html> | + | <a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/dup.html"></html> |
''int **dup**(int //fildes//)'' \\ | ''int **dup**(int //fildes//)'' \\ | ||
''int **dup2**(int //fildes//, int //target//)'' | ''int **dup2**(int //fildes//, int //target//)'' | ||
Line 297: | Line 305: | ||
wrote something. | wrote something. | ||
- | When a function stops not because it is not given the CPU time but because it | + | When a function that interfaces with the operating system does not return because |
- | waits for something to happen, then it **blocks**. | + | the OS waits for something to happen before it may respond, then one says that |
+ | the function **blocks**. | ||
\\ | \\ | ||
- | Functions that may block are called **blocking**. (Cf. definition of | + | Functions that may ever block are called **blocking**. (Cf. definition of |
- | [[https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_77|blocking]] | + | [[https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap03.html#tag_03_48|blocking]] |
in POSIX standard.) | in POSIX standard.) | ||
Line 321: | Line 330: | ||
\\ | \\ | ||
To set/clear the O_NONBLOCK flag, one shall first read the flags with | To set/clear the O_NONBLOCK flag, one shall first read the flags with | ||
- | ''int flags = [[https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html|fcntl]](fd, F_GETFL);'', | + | ''int flags = [[https://pubs.opengroup.org/onlinepubs/9799919799/functions/fcntl.html|fcntl]](fd, F_GETFL);'', |
then set/clear the flag (e.g., ''flags |= O_NONBLOCK;'') and finally set the | then set/clear the flag (e.g., ''flags |= O_NONBLOCK;'') and finally set the | ||
new flags with ''fcntl(fd, F_SETFL, flags);''. | new flags with ''fcntl(fd, F_SETFL, flags);''. | ||
Line 332: | Line 341: | ||
\\ | \\ | ||
<html><span style="float:right"><small>Needs header: <code>unistd.h</code></small></span> | <html><span style="float:right"><small>Needs header: <code>unistd.h</code></small></span> | ||
- | <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html"></html> | + | <a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/pipe.html"></html> |
''int **pipe**(int //fildes//[2])'' | ''int **pipe**(int //fildes//[2])'' | ||
<html></a></html> | <html></a></html> | ||
\\ | \\ | ||
The ''//fildes//[0]'' is opened for reading, and the ''//fildes//[1]'' is opened | The ''//fildes//[0]'' is opened for reading, and the ''//fildes//[1]'' is opened | ||
- | for writing. | + | for writing. <small>(Cf. with standard input being ''0'' and standard output being ''1'')</small> |
\\ | \\ | ||
Pipes can be used to send data from one process to another process, or from | Pipes can be used to send data from one process to another process, or from | ||
Line 366: | Line 375: | ||
end of a pipe by providing a path to the file. A FIFO file can be created with | end of a pipe by providing a path to the file. A FIFO file can be created with | ||
''mkfifo'' shell utility or by the | ''mkfifo'' shell utility or by the | ||
- | ''[[https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifo.html|mkfifo]]'' | + | ''[[https://pubs.opengroup.org/onlinepubs/9799919799/functions/mkfifo.html|mkfifo]]'' |
function. | function. | ||
\\ | \\ |