This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
|
os_cp:fork_exec_pipes [2024/05/08 13:31] jkonczak utworzono |
os_cp:fork_exec_pipes [2026/05/20 20:31] (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 20: | Line 20: | ||
| There is a list of things that ''fork'' does not clone or that are reset for the | There is a list of things that ''fork'' does not clone or that are reset for the | ||
| - | child process upon ''fork''. See POSIX standard or Linux manual on fork for details. | + | child process upon ''fork''. |
| + | \\ See POSIX standard or | ||
| + | [[https://man7.org/linux/man-pages/man2/fork.2.html|Linux manual on fork]] | ||
| + | for details. | ||
| + | \\ | ||
| Notice that: | Notice that: | ||
| * all stack and heap memory is copied | * all stack and heap memory is copied | ||
| Line 33: | Line 37: | ||
| 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 43: | ||
| 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 61: | ||
| \\ | \\ | ||
| <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 95: | ||
| \\ | \\ | ||
| 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 121: | ||
| 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 149: | ||
| 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 155: | Line 164: | ||
| <html><div style="margin-bottom:-1.4em"></div></html> | <html><div style="margin-bottom:-1.4em"></div></html> | ||
| <code c> | <code c> | ||
| - | char arg0[] = "ls"; char arg2[] = "-a"; | ||
| - | char arg1[] = "-l"; char arg3[] = "/tmp"; | ||
| # Argument list: | # Argument list: | ||
| - | execlp("ls", arg0, arg1, arg2, arg3, NULL); | + | execlp("ls", "ls", "-l", "-a", "/tmp", NULL); |
| - | # Argument vector: | + | |
| - | char *argv[] = {arg0, arg1, arg2, arg3, NULL}; | + | # Argument vector: |
| + | char *argv[] = {"ls", "-l", "-a", "/tmp", NULL}; | ||
| execvp("ls", argv); | execvp("ls", argv); | ||
| </code> | </code> | ||
| Line 192: | Line 200: | ||
| <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 209: | ||
| (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 226: | ||
| <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 236: | ||
| 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><div style="margin-top:-1.4em"></HTML> | ||
| + | Instead of the C11 function ''[[https://en.cppreference.com/c/chrono/timespec_get|timespec_get]](&//x//, TIME_UTC);'', you may also | ||
| + | use the POSIX function ''[[https://pubs.opengroup.org/onlinepubs/9799919799/functions/clock_gettime.html|clock_gettime]](CLOCK_MONOTONIC, &//x//);''. | ||
| + | <HTML></div></HTML> | ||
| </small> | </small> | ||
| Line 239: | Line 253: | ||
| 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 311: | ||
| 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 336: | ||
| \\ | \\ | ||
| 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 347: | ||
| \\ | \\ | ||
| <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 381: | ||
| 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. | ||
| \\ | \\ | ||
| Line 378: | Line 393: | ||
| <small>Pipe is unidirectional. The unix //socket// is its bidirectional | <small>Pipe is unidirectional. The unix //socket// is its bidirectional | ||
| equivalent. See ''[[https://man7.org/linux/man-pages/man7/unix.7.html|man 7 unix]]'' | equivalent. See ''[[https://man7.org/linux/man-pages/man7/unix.7.html|man 7 unix]]'' | ||
| - | for details.</small> | + | for details. |
| + | \\ | ||
| + | POSIX standard also defines (but not mandates) | ||
| + | [[https://man7.org/linux/man-pages/man7/mq_overview.7.html|message queues]]. | ||
| + | </small> | ||
| ~~Exercise.#~~ Write a program that: | ~~Exercise.#~~ Write a program that: | ||