0% found this document useful (0 votes)
16 views9 pages

Thread Variable Optimization Entropya3b675d1

Uploaded by

bergen.raheem
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views9 pages

Thread Variable Optimization Entropya3b675d1

Uploaded by

bergen.raheem
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

2 I NTERLUDE : P ROCESS API

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4

5 int main(int argc, char *argv[]) {


6 printf("hello (pid:%d)\n", (int) getpid());
7 int rc = fork();
8 if (rc < 0) {
9 // fork failed
10 fprintf(stderr, "fork failed\n");
11 exit(1);
12 } else if (rc == 0) {
13 // child (new process)
14 printf("child (pid:%d)\n", (int) getpid());
15 } else {
16 // parent goes down this path (main)
17 printf("parent of %d (pid:%d)\n",
18 rc, (int) getpid());
19 }
20 return 0;
21 }
22
Figure 5.1: Calling fork() (p1.c)
When you run this program (called p1.c), you’ll see the following:

prompt> ./p1
hello (pid:29146)
parent of 29147 (pid:29146)
child (pid:29147)
prompt>

Let us understand what happened in more detail in p1.c. When it


first started running, the process prints out a hello message; included in
that message is its process identifier, also known as a PID. The process
has a PID of 29146; in U NIX systems, the PID is used to name the process
if one wants to do something with the process, such as (for example) stop
it from running. So far, so good.
Now the interesting part begins. The process calls the fork() system
call, which the OS provides as a way to create a new process. The odd
part: the process that is created is an (almost) exact copy of the calling pro-
cess. That means that to the OS, it now looks like there are two copies of
the program p1 running, and both are about to return from the fork()
system call. The newly-created process (called the child, in contrast to the
creating parent) doesn’t start running at main(), like you might expect
(note, the “hello” message only got printed out once); rather, it just comes
into life as if it had called fork() itself.

O PERATING
S YSTEMS WWW. OSTEP. ORG
[V ERSION 1.10]
2 I NTERLUDE : P ROCESS API

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4

5 int main(int argc, char *argv[]) {


6 printf("hello (pid:%d)\n", (int) getpid());
7 int rc = fork();
8 if (rc < 0) {
9 // fork failed
10 fprintf(stderr, "fork failed\n");
11 exit(1);
12 } else if (rc == 0) {
13 // child (new process)
14 printf("child (pid:%d)\n", (int) getpid());
15 } else {
16 // parent goes down this path (main)
17 printf("parent of %d (pid:%d)\n",
18 rc, (int) getpid());
19 }
20 return 0;
21 }
22
Figure 5.1: Calling fork() (p1.c)
When you run this program (called p1.c), you’ll see the following:

prompt> ./p1
hello (pid:29146)
parent of 29147 (pid:29146)
child (pid:29147)
prompt>

Let us understand what happened in more detail in p1.c. When it


first started running, the process prints out a hello message; included in
that message is its process identifier, also known as a PID. The process
has a PID of 29146; in U NIX systems, the PID is used to name the process
if one wants to do something with the process, such as (for example) stop
it from running. So far, so good.
Now the interesting part begins. The process calls the fork() system
call, which the OS provides as a way to create a new process. The odd
part: the process that is created is an (almost) exact copy of the calling pro-
cess. That means that to the OS, it now looks like there are two copies of
the program p1 running, and both are about to return from the fork()
system call. The newly-created process (called the child, in contrast to the
creating parent) doesn’t start running at main(), like you might expect
(note, the “hello” message only got printed out once); rather, it just comes
into life as if it had called fork() itself.

O PERATING
S YSTEMS WWW. OSTEP. ORG
[V ERSION 1.10]
2 I NTERLUDE : P ROCESS API

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4

5 int main(int argc, char *argv[]) {


6 printf("hello (pid:%d)\n", (int) getpid());
7 int rc = fork();
8 if (rc < 0) {
9 // fork failed
10 fprintf(stderr, "fork failed\n");
11 exit(1);
12 } else if (rc == 0) {
13 // child (new process)
14 printf("child (pid:%d)\n", (int) getpid());
15 } else {
16 // parent goes down this path (main)
17 printf("parent of %d (pid:%d)\n",
18 rc, (int) getpid());
19 }
20 return 0;
21 }
22
Figure 5.1: Calling fork() (p1.c)
When you run this program (called p1.c), you’ll see the following:

prompt> ./p1
hello (pid:29146)
parent of 29147 (pid:29146)
child (pid:29147)
prompt>

Let us understand what happened in more detail in p1.c. When it


first started running, the process prints out a hello message; included in
that message is its process identifier, also known as a PID. The process
has a PID of 29146; in U NIX systems, the PID is used to name the process
if one wants to do something with the process, such as (for example) stop
it from running. So far, so good.
Now the interesting part begins. The process calls the fork() system
call, which the OS provides as a way to create a new process. The odd
part: the process that is created is an (almost) exact copy of the calling pro-
cess. That means that to the OS, it now looks like there are two copies of
the program p1 running, and both are about to return from the fork()
system call. The newly-created process (called the child, in contrast to the
creating parent) doesn’t start running at main(), like you might expect
(note, the “hello” message only got printed out once); rather, it just comes
into life as if it had called fork() itself.

O PERATING
S YSTEMS WWW. OSTEP. ORG
[V ERSION 1.10]
I NTERLUDE : P ROCESS API 5

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <sys/wait.h>
6

7 int main(int argc, char *argv[]) {


8 printf("hello (pid:%d)\n", (int) getpid());
9 int rc = fork();
10 if (rc < 0) { // fork failed; exit
11 fprintf(stderr, "fork failed\n");
12 exit(1);
13 } else if (rc == 0) { // child (new process)
14 printf("child (pid:%d)\n", (int) getpid());
15 char *myargs[3];
16 myargs[0] = strdup("wc"); // program: "wc"
17 myargs[1] = strdup("p3.c"); // arg: input file
18 myargs[2] = NULL; // mark end of array
19 execvp(myargs[0], myargs); // runs word count
20 printf("this shouldn’t print out");
21 } else { // parent goes down this path
22 int rc_wait = wait(NULL);
23 printf("parent of %d (rc_wait:%d) (pid:%d)\n",
24 rc, rc_wait, (int) getpid());
25 }
26 return 0;
27 }
28
Figure 5.3: Calling fork(), wait(), And exec() (p3.c)
in p2.c is only useful if you want to keep running copies of the same
program. However, often you want to run a different program; exec()
does just that (Figure 5.3).
In this example, the child process calls execvp() in order to run the
program wc, which is the word counting program. In fact, it runs wc on
the source file p3.c, thus telling us how many lines, words, and bytes are
found in the file:

prompt> ./p3
hello (pid:29383)
child (pid:29384)
29 107 1030 p3.c
parent of 29384 (rc_wait:29384) (pid:29383)
prompt>

The fork() system call is strange; its partner in crime, exec(), is not
so normal either. What it does: given the name of an executable (e.g., wc),
and some arguments (e.g., p3.c), it loads code (and static data) from that

T HREE
© 2008–23, A RPACI -D USSEAU
E ASY
P IECES
I NTERLUDE : P ROCESS API 5

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <sys/wait.h>
6

7 int main(int argc, char *argv[]) {


8 printf("hello (pid:%d)\n", (int) getpid());
9 int rc = fork();
10 if (rc < 0) { // fork failed; exit
11 fprintf(stderr, "fork failed\n");
12 exit(1);
13 } else if (rc == 0) { // child (new process)
14 printf("child (pid:%d)\n", (int) getpid());
15 char *myargs[3];
16 myargs[0] = strdup("wc"); // program: "wc"
17 myargs[1] = strdup("p3.c"); // arg: input file
18 myargs[2] = NULL; // mark end of array
19 execvp(myargs[0], myargs); // runs word count
20 printf("this shouldn’t print out");
21 } else { // parent goes down this path
22 int rc_wait = wait(NULL);
23 printf("parent of %d (rc_wait:%d) (pid:%d)\n",
24 rc, rc_wait, (int) getpid());
25 }
26 return 0;
27 }
28
Figure 5.3: Calling fork(), wait(), And exec() (p3.c)
in p2.c is only useful if you want to keep running copies of the same
program. However, often you want to run a different program; exec()
does just that (Figure 5.3).
In this example, the child process calls execvp() in order to run the
program wc, which is the word counting program. In fact, it runs wc on
the source file p3.c, thus telling us how many lines, words, and bytes are
found in the file:

prompt> ./p3
hello (pid:29383)
child (pid:29384)
29 107 1030 p3.c
parent of 29384 (rc_wait:29384) (pid:29383)
prompt>

The fork() system call is strange; its partner in crime, exec(), is not
so normal either. What it does: given the name of an executable (e.g., wc),
and some arguments (e.g., p3.c), it loads code (and static data) from that

T HREE
© 2008–23, A RPACI -D USSEAU
E ASY
P IECES
I NTERLUDE : P ROCESS API 5

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <sys/wait.h>
6

7 int main(int argc, char *argv[]) {


8 printf("hello (pid:%d)\n", (int) getpid());
9 int rc = fork();
10 if (rc < 0) { // fork failed; exit
11 fprintf(stderr, "fork failed\n");
12 exit(1);
13 } else if (rc == 0) { // child (new process)
14 printf("child (pid:%d)\n", (int) getpid());
15 char *myargs[3];
16 myargs[0] = strdup("wc"); // program: "wc"
17 myargs[1] = strdup("p3.c"); // arg: input file
18 myargs[2] = NULL; // mark end of array
19 execvp(myargs[0], myargs); // runs word count
20 printf("this shouldn’t print out");
21 } else { // parent goes down this path
22 int rc_wait = wait(NULL);
23 printf("parent of %d (rc_wait:%d) (pid:%d)\n",
24 rc, rc_wait, (int) getpid());
25 }
26 return 0;
27 }
28
Figure 5.3: Calling fork(), wait(), And exec() (p3.c)
in p2.c is only useful if you want to keep running copies of the same
program. However, often you want to run a different program; exec()
does just that (Figure 5.3).
In this example, the child process calls execvp() in order to run the
program wc, which is the word counting program. In fact, it runs wc on
the source file p3.c, thus telling us how many lines, words, and bytes are
found in the file:

prompt> ./p3
hello (pid:29383)
child (pid:29384)
29 107 1030 p3.c
parent of 29384 (rc_wait:29384) (pid:29383)
prompt>

The fork() system call is strange; its partner in crime, exec(), is not
so normal either. What it does: given the name of an executable (e.g., wc),
and some arguments (e.g., p3.c), it loads code (and static data) from that

T HREE
© 2008–23, A RPACI -D USSEAU
E ASY
P IECES
8 I NTERLUDE : P ROCESS API

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <fcntl.h>
6 #include <sys/wait.h>
7

8 int main(int argc, char *argv[]) {


9 int rc = fork();
10 if (rc < 0) {
11 // fork failed
12 fprintf(stderr, "fork failed\n");
13 exit(1);
14 } else if (rc == 0) {
15 // child: redirect standard output to a file
16 close(STDOUT_FILENO);
17 open("./p4.output", O_CREAT|O_WRONLY|O_TRUNC,
18 S_IRWXU);
19 // now exec "wc"...
20 char *myargs[3];
21 myargs[0] = strdup("wc"); // program: wc
22 myargs[1] = strdup("p4.c"); // arg: file to count
23 myargs[2] = NULL; // mark end of array
24 execvp(myargs[0], myargs); // runs word count
25 } else {
26 // parent goes down this path (main)
27 int rc_wait = wait(NULL);
28 }
29 return 0;
30 }
Figure 5.4: All Of The Above With Redirection (p4.c)

5.5 Process Control And Users


Beyond fork(), exec(), and wait(), there are a lot of other inter-
faces for interacting with processes in U NIX systems. For example, the
kill() system call is used to send signals to a process, including di-
rectives to pause, die, and other useful imperatives. For convenience,
in most U NIX shells, certain keystroke combinations are configured to
deliver a specific signal to the currently running process; for example,
control-c sends a SIGINT (interrupt) to the process (normally terminating
it) and control-z sends a SIGTSTP (stop) signal thus pausing the process
in mid-execution (you can resume it later with a command, e.g., the fg
built-in command found in many shells).
The entire signals subsystem provides a rich infrastructure to deliver
external events to processes, including ways to receive and process those
signals within individual processes, and ways to send signals to individ-
ual processes as well as entire process groups. To use this form of com-

O PERATING
S YSTEMS WWW. OSTEP. ORG
[V ERSION 1.10]
8 I NTERLUDE : P ROCESS API

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <fcntl.h>
6 #include <sys/wait.h>
7

8 int main(int argc, char *argv[]) {


9 int rc = fork();
10 if (rc < 0) {
11 // fork failed
12 fprintf(stderr, "fork failed\n");
13 exit(1);
14 } else if (rc == 0) {
15 // child: redirect standard output to a file
16 close(STDOUT_FILENO);
17 open("./p4.output", O_CREAT|O_WRONLY|O_TRUNC,
18 S_IRWXU);
19 // now exec "wc"...
20 char *myargs[3];
21 myargs[0] = strdup("wc"); // program: wc
22 myargs[1] = strdup("p4.c"); // arg: file to count
23 myargs[2] = NULL; // mark end of array
24 execvp(myargs[0], myargs); // runs word count
25 } else {
26 // parent goes down this path (main)
27 int rc_wait = wait(NULL);
28 }
29 return 0;
30 }
Figure 5.4: All Of The Above With Redirection (p4.c)

5.5 Process Control And Users


Beyond fork(), exec(), and wait(), there are a lot of other inter-
faces for interacting with processes in U NIX systems. For example, the
kill() system call is used to send signals to a process, including di-
rectives to pause, die, and other useful imperatives. For convenience,
in most U NIX shells, certain keystroke combinations are configured to
deliver a specific signal to the currently running process; for example,
control-c sends a SIGINT (interrupt) to the process (normally terminating
it) and control-z sends a SIGTSTP (stop) signal thus pausing the process
in mid-execution (you can resume it later with a command, e.g., the fg
built-in command found in many shells).
The entire signals subsystem provides a rich infrastructure to deliver
external events to processes, including ways to receive and process those
signals within individual processes, and ways to send signals to individ-
ual processes as well as entire process groups. To use this form of com-

O PERATING
S YSTEMS WWW. OSTEP. ORG
[V ERSION 1.10]
8 I NTERLUDE : P ROCESS API

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <fcntl.h>
6 #include <sys/wait.h>
7

8 int main(int argc, char *argv[]) {


9 int rc = fork();
10 if (rc < 0) {
11 // fork failed
12 fprintf(stderr, "fork failed\n");
13 exit(1);
14 } else if (rc == 0) {
15 // child: redirect standard output to a file
16 close(STDOUT_FILENO);
17 open("./p4.output", O_CREAT|O_WRONLY|O_TRUNC,
18 S_IRWXU);
19 // now exec "wc"...
20 char *myargs[3];
21 myargs[0] = strdup("wc"); // program: wc
22 myargs[1] = strdup("p4.c"); // arg: file to count
23 myargs[2] = NULL; // mark end of array
24 execvp(myargs[0], myargs); // runs word count
25 } else {
26 // parent goes down this path (main)
27 int rc_wait = wait(NULL);
28 }
29 return 0;
30 }
Figure 5.4: All Of The Above With Redirection (p4.c)

5.5 Process Control And Users


Beyond fork(), exec(), and wait(), there are a lot of other inter-
faces for interacting with processes in U NIX systems. For example, the
kill() system call is used to send signals to a process, including di-
rectives to pause, die, and other useful imperatives. For convenience,
in most U NIX shells, certain keystroke combinations are configured to
deliver a specific signal to the currently running process; for example,
control-c sends a SIGINT (interrupt) to the process (normally terminating
it) and control-z sends a SIGTSTP (stop) signal thus pausing the process
in mid-execution (you can resume it later with a command, e.g., the fg
built-in command found in many shells).
The entire signals subsystem provides a rich infrastructure to deliver
external events to processes, including ways to receive and process those
signals within individual processes, and ways to send signals to individ-
ual processes as well as entire process groups. To use this form of com-

O PERATING
S YSTEMS WWW. OSTEP. ORG
[V ERSION 1.10]

You might also like