Upload
bernadette-neal
View
217
Download
0
Embed Size (px)
DESCRIPTION
3 Process – SW View “A [Bryant, 16] “A process is the operating system’s abstraction of a running program.” [Silberschatz, 10] “A [Silberschatz, 10] “A process can be thought of as a program in execution …” [Silberschatz, 90] “Informally, a [Silberschatz, 90] “Informally, a process is a program in execution. … A process is more than the program code. It also includes the current activity, as represented by the value of the program counter and the contents of the processor’s registers.” “A [Tanenbaum, 72] “A process is just an executing program, including the current values of the program counter, registers, and variables.”
Citation preview
1
CS 201Computer Systems Programming
Chapter 8“Unix fork(), execve()”
Herbert G. Mayer, PSU CSHerbert G. Mayer, PSU CSStatus 2/18/2013Status 2/18/2013
2
Syllabus Process, Thread, HyperthreadProcess, Thread, Hyperthread Unix ProcessUnix Process InterruptInterrupt Command Command psps Background ProcessBackground Process Command Command fork()fork() fork() fork() SampleSample Command Command execve()execve() execve() execve() SampleSample ReferencesReferences
3
Process – SW View [Bryant, 16] “A“A process is the operating system’s
abstraction of a running program.” [Silberschatz, 10] “A[Silberschatz, 10] “A process can be thought of as a
program in execution …” [Silberschatz, 90] “Informally, a[Silberschatz, 90] “Informally, a process is a program
in execution. … A process is more than the program code. It also includes the current activity, as represented by the value of the program counter and the contents of the processor’s registers.”
[Tanenbaum, 72] “A“A process is just an executing program, including the current values of the program counter, registers, and variables.”
4
Thread – SW View [Bryant, 947] “A[Bryant, 947] “A thread is a logical flow that runs in the context
of a process. Each thread has its own thread context, including a unique integer thread ID, stack, stack pointer, program counter, general-purpose registers, and condition codes. All threads running in a process share the entire virtual address space of that process.”
[Silberschatz, 103] “A thread, sometimes called a lightweight process, is a basic unit of CPU utilization, and consists of a program counter, a register set, and a stack space. It shares with peer threads its code section, data section, and operating-system resources such as open files and signals.”
[Tanenbaum, 81] “A thread has a program counter that keeps track of which instruction to execute next. It has registers, which hold its current working variables. It has a stack, which contains the execution history, with one frame for each procedure called, but not yet returned from. ... A thread must execute in some process”
5
Hyperthread – HW View A processor may be A processor may be single-core single-core (UP), o(UP), or have multiple
cores, the latter meaning: all processor resources are replicated; e.g. Intel Core 2 Duo
Or a processor may be single-core, hyperthreaded, e.g. Intel Pentium 4e. Hyperthreaded means that only CPU registers and APIC are replicated, but not ALU units, such as integer unit, floating-point unit, branch unit, caches, etc.
Or a processor may be multi-core, hyperthreaded, in which case each of several real cores has a hyperthread twin, sharing the real core’s ALU with a hyperthread, but each hyperthread has own register + APIC; e.g. Intel Core i7
Hyperthreading is an old technology, proposed decades ago by Digital Equipment Corp. (DEC), and implemented for the first time in silicon by Intel in 2002 on Xeon® server and Pentium® 4 desktop CPUs
Hyperthread is an overloaded term, referring to the reduced Silicon core, as well as the SW thread executing on it
Should be named: Should be named: HypothreadHypothread since it is a since it is a subsubsetset
6
Hyperthread – Per Intel WebsiteAbility of processor to run concurrent threads quicklyAbility of processor to run concurrent threads quickly
Some microprocessor hardware replication that creates the illusion to SW of Dual Processor (DP)
Yet such HW with some resource replication is NOT a true dual-core silicon implementation
The execution unit is still shared between multiple threads
Effect of Hyperthreading on XeonEffect of Hyperthreading on Xeon®® Processor: Processor: Average CPU utilization increases to ~50%, down from
~35% for a typical uni-processor Up to ~30% performance gain for some applications with
the same processor frequency
Hyperthreading Technology Results:Hyperthreading Technology Results:1. More performance with enabled applications1. More performance with enabled applications2. Better responsiveness with existing applications2. Better responsiveness with existing applications
7
Hyperthread – Per Intel WebsiteAlmostAlmost two Logical Processors two Logical Processors
Architecture state (registers) and Architecture state (registers) and APIC* replicatedAPIC* replicated
Shares execution units, caches, Shares execution units, caches, branch prediction, control logic branch prediction, control logic and busesand buses
ProcessorExecutionResource
Adv. ProgrammableInterrupt Control
Architecture State
Adv. ProgrammableInterrupt Control
Architecture State
On-DieCaches
System Bus
*APIC: Advanced Programmable *APIC: Advanced Programmable Interrupt Controller. Handles Interrupt Controller. Handles interrupts sent to a specified logical interrupts sent to a specified logical processorprocessor
8
Hyperthread Hyperthreaded core only replicates in HW, silicon, those CPU
resources essential to switching from one thread to another Those replicated resources are registers and the APIC. ALU
units are not replicated on hyperthreaded core SW hyperthreads are also threads, but execute concurrently SW hyperthreads are also threads, but execute concurrently
on HW hyperthread cores; switch is efficient due to available on HW hyperthread cores; switch is efficient due to available registers; sharing still necessary due to single ALUregisters; sharing still necessary due to single ALU
This costs ~5% more HW (silicon) than a single core, but can gain up to 30% performance improvement; great ROI!
9
Delta Between Process & Thread ProcessProcess is an OS-centric view of a running program. is an OS-centric view of a running program.
Due to the meaning of “running”, all machine Due to the meaning of “running”, all machine resources are necessary to execute a processresources are necessary to execute a process
A thread is a subset of a process, not necessarily a proper subset; or: “a thread is part of a process”
One purpose for threading a process is to allow continued execution, even when some part of such a process waits; e.g. one thread waits for an IO operation to finish, but another thread can continue
Purpose for having threads execute a process is to speed up overall execution. Possible, if multiple threads of the same process are sufficiently data-independent to progress concurrently. But never simultaneously on a single core!
10
Delta Between Thread & Hyperthread A hyperthreaded core A hyperthreaded core almostalmost creates illusion of a creates illusion of a
multi-core CPU, though there is only 1 complete CPUmulti-core CPU, though there is only 1 complete CPU Enables concurrent execution on a uni-processor,
when one process thread stalls and another thread is ready; switch to the other thread is cheap, if the other register set already has the proper state
But hyperthreading per se never allows parallel execution; only a multi-core architecture does
A System Programmer needs to know: On an OS not yet tuned for hyper-threading: best disable multi-core scheduling, else under the right (i.e. the wrong circumstances) performance degradation results
This is the case, when the “next core to be scheduled” happens to be regularly the hyperthreaded subset-core, leaving some other real core idle, while the real core could work instead of the hyperthread
11
Unix Process Under Unix, aUnder Unix, a process is an instance of running a
program. If you execute the ancient editor ed and your colleague does too, then there are 2 very similar processes running
All user a.out programs and all Unix commands, when running, become processes; commands ll or g++ my_prog.cpp create processes
Processes are visible via ps command, and even that command is a process of its own right
Issue the command ps, for process status, and you see your current processes, plus the ps processes
Issue ps –a, and you see a long list, including sleeping processes
Issue the command man ps for your education
12
Interrupt Def: Program interrupt is a transparent, non-
scheduled change in execution flow with specific cause outside the program, treated by an interrupt handler, ending up at original program again
Is unpredictable: Programmer does not know that, when, where interrupt happens
Is unexpected: Programmer does not know when interrupt happens
Cannot be pinpointed: Programmer does not know where interrupt happens
Cause is known, passed to interrupt handler, yet the program does not know a-priori that it will happen; can be some external event like power-outage, or timer iterrupt
13
Interrupt After handling, execution continues at place after the
interrupt Challenge: if interrupt happens during execution of
some long instruction, say move of a large portion of memory by a move-byte instruction
Challenge caused by general need of handling interrupt swiftly, more swiftly than the time needed for some long machine instructions!
Interrupt handled in a way that the program never knows it was interrupted: transparent
Except that execution ended up to be slower than expected; slower than if the interrupt had not happened
Note: x86 INT instruction is not an interrupt! Though it is named a “software interrupt” instruction; is it totally predictable, locatable
14
Unix Process When you issue a command, Unix starts a new
process, suspends the current process, generally the C-shell, until the new child process completes
Exception: background processes with & Unix identifies every process by a Process
Identification Number (PID) assigned at initiation See getpid() function calls below Unix is a timesharing system, which grants each
process a time-slice Allocation of time-slices has to be fair, so that one
long process cannot make other, shorter ones, wait for extended periods (no starvation!)
Also, time-slicing has to be efficient, lest much processing time migrates into overhead, like a typical state government
15
Command ps Command Command ps ps prints information about active prints information about active
processes; key resource for System Programmerprocesses; key resource for System Programmer It is quite complex, with many optionsIt is quite complex, with many options Without any option, command shows all processes Without any option, command shows all processes
for the same user id as the one issuing the for the same user id as the one issuing the command; see below: command; see below: PIDPID identifies the process, identifies the process, TTTT the controlling terminal, the controlling terminal, SS the state, and the state, and TIMETIME the CPU time consumed for that processthe CPU time consumed for that process
[process] ps[process] ps PID TT S TIME COMMANDPID TT S TIME COMMAND 8687 pts/33 O 0:00 ps8687 pts/33 O 0:00 ps -- O running-- O running 19212 pts/33 S 0:00 –csh19212 pts/33 S 0:00 –csh -- S sleepin-- S sleepingg
16
Command psThe command The command ps –aps –a prints information about all active prints information about all active processes; can result in a long list, e.g.:processes; can result in a long list, e.g.:
ps –a | moreps –a | more PID TT S TIME COMMANDPID TT S TIME COMMAND 12229 Z 0:00 12229 Z 0:00 16386 Z 0:00 16386 Z 0:00 523 console S 0:00 /usr/lib/saf/ttymon 523 console S 0:00 /usr/lib/saf/ttymon -g -d /dev/console -l console -m ld-g -d /dev/console -l console -m ld 19668 pts/1 S 0:00 -tcsh19668 pts/1 S 0:00 -tcsh 19691 pts/1 S 0:00 tcsh19691 pts/1 S 0:00 tcsh 19705 pts/1 S 0:07 pine19705 pts/1 S 0:07 pine 22394 pts/2 S 0:00 -bash22394 pts/2 S 0:00 -bash 22412 pts/2 S 0:06 screen22412 pts/2 S 0:06 screen. . . . . .
17
Command ps
To abort, AKA kill, any process in Unix whose PID To abort, AKA kill, any process in Unix whose PID is known, issue the command is known, issue the command killkill with argument with argument -9, e.g.:-9, e.g.:
kill –9 19186kill –9 19186 Which in this particular case was the instructor’s Which in this particular case was the instructor’s
remote shell log in to PSU’s computer, and as a remote shell log in to PSU’s computer, and as a result he had to log in again result he had to log in again from home from home
18
Background Process & Some processes may run foreverSome processes may run forever Others in your environment may run for a limited Others in your environment may run for a limited
time but for quite longtime but for quite long What if you do not wish to wait for long process What if you do not wish to wait for long process
completion before continuing with other work?completion before continuing with other work? Addressed in Unix with Addressed in Unix with background background processes processes
that can be initiated by the that can be initiated by the && command modifier, command modifier, such as:such as:
run_big &run_big & Which executes a long running program Which executes a long running program run_bigrun_big
but in the background; making progress whenever but in the background; making progress whenever CPU cycles are availableCPU cycles are available
Your real interactive work may proceeded in Your real interactive work may proceeded in parallel –on a UP of course: parallel –on a UP of course: concurrentlyconcurrently
19
Background Process & What happens if this program generates output, What happens if this program generates output,
such as messages to such as messages to stderrstderr?? These would be interspersed with other output These would be interspersed with other output
generated concurrentlygenerated concurrently To avoid mixing of messages, To avoid mixing of messages, stderr stderr can be can be
redirected to a separate file using redirected to a separate file using >&>&g++ big_program.cpp >& my_errors &g++ big_program.cpp >& my_errors &
. . . does accomplish that. . . does accomplish that It redirects via It redirects via >&>& all output from all output from stderr stderr to a new to a new
file, named: file, named: my_errorsmy_errors … … and then runs in the background, caused by and then runs in the background, caused by && So neither the messages nor the (long running) So neither the messages nor the (long running)
background process hold you upbackground process hold you up
20
Command fork() Unix command Unix command fork()fork() creates a new process by creates a new process by
cloning the current process issuing the cloning the current process issuing the fork()fork() commandcommand
Peculiar about a child processes: it shares all Peculiar about a child processes: it shares all attributes with the forking parent process, except for attributes with the forking parent process, except for process id, AKA process id, AKA PIDPID, parent PID AKA , parent PID AKA PPIDPPID, , lockslocks and a few attributes and a few attributes preventing infinite spawningpreventing infinite spawning
To correctly compile the To correctly compile the fork()fork() command in your command in your C++ program, C++ program, #include <unistd.h>#include <unistd.h>
Code and data space of child and parent process are Code and data space of child and parent process are shared shared for reading onlyfor reading only; when the child needs to ; when the child needs to write (stack, heap) it receives its own copy with the write (stack, heap) it receives its own copy with the new new modificationsmodifications; ; AKAAKA copy-on-write copy-on-write
Spawning a new process via Spawning a new process via fork()fork() creates a creates a second second exit()exit() action action
21
Command fork() Confusing about Confusing about fork()fork() is that it creates one new is that it creates one new
process by cloning once, but exiting twiceprocess by cloning once, but exiting twice Child can inquire about its own PID via Child can inquire about its own PID via getpid( )getpid( ) Child processes created via Child processes created via fork()fork() do not repeat do not repeat
their own their own fork()fork() thus thus preventing infinite spawningpreventing infinite spawning But child processes do execute other But child processes do execute other fork()fork() Important: child and parent run concurrentlyImportant: child and parent run concurrently
If they had 2 processors, they could run in parallel, but the relative speeds are arbitrary! Make no assumptions about their speeds
Hence these 2 executions can be arbitrarily interleaved E.g. outputs can be arbitrarily interleaved, though strictly
sequential for parent and strictly sequential for the child A sample shown next:A sample shown next:
22
fork() Sample1#define DEAD -1#define DEAD -1#include <unistd.h>#include <unistd.h> // must include for fork() // must include for fork()void fork_sample1()void fork_sample1(){ // fork_sample1{ // fork_sample1 int int local local = 1; // track: which process? = 1; // track: which process? pid_t pid = pid_t pid = fork()fork(); // from now on: 2 processes; // from now on: 2 processes switch ( pid ) {switch ( pid ) { case 0:case 0: // this is thread through child process// this is thread through child process cout << " cout << " locallocal in child = " << in child = " << ++local ++local << endl;<< endl; break;break; case DEAD:case DEAD: // this is en error process, dead, zombie?// this is en error process, dead, zombie? cout << ” cout << ” locallocal in DEAD process " << local << endl; in DEAD process " << local << endl; break;break; default:default: // clearly thread through parent process// clearly thread through parent process cout << " cout << " locallocal in parent = " << in parent = " << --local --local << endl;<< endl; } //end switch} //end switch // switch statement with multiple clauses executed!// switch statement with multiple clauses executed! cout << "Ending process " << pid << endl;cout << "Ending process " << pid << endl;} //end fork_sample1} //end fork_sample1
23
fork() Sample1 Output[process] a.out[process] a.out local in parent = 0local in parent = 0Ending process 16644Ending process 16644 local in child = 2local in child = 2Ending process 0Ending process 0[process][process]
•Note that Note that locallocal is 2, and not 1 in child process, and it is 2, and not 1 in child process, and it happens to be executed after parenthappens to be executed after parent
•So you infer: So you infer: child has its own copychild has its own copy. It does not share . It does not share locallocal with parent; else it would be 1, since parent with parent; else it would be 1, since parent decreased decreased locallocal to 0 to 0
•Students: Are other outputs possible? How many?Students: Are other outputs possible? How many?
24
fork() Sample2#define DEAD -1#define DEAD -1 // define DEAD as before// define DEAD as before#include <unistd>#include <unistd> // make fork() available// make fork() available
// Bryant & O'Halleron's "Computer Systems", chapter 8// Bryant & O'Halleron's "Computer Systems", chapter 8void fork_sample2()void fork_sample2(){ // fork_sample2{ // fork_sample2 switch ( switch ( fork()fork() ) { ) { case 0:case 0: // is the child's thread// is the child's thread cout << 'C';cout << 'C'; break;break; case DEAD:case DEAD: cout << " <><> DEAD process?";cout << " <><> DEAD process?"; break;break; default:default: // is the parent's process// is the parent's process cout << 'P';cout << 'P'; } //end switch} //end switch // in all cases, indicate end by emitting 'E'// in all cases, indicate end by emitting 'E' cout << 'E';cout << 'E';} //end fork_sample2} //end fork_sample2
25
fork() Sample2 Output[process] a.out[process] a.outPECE[process]PECE[process]
•Would CEPE be possible?Would CEPE be possible?•Would CPEE be possible?Would CPEE be possible?•Would EECP be possible?Would EECP be possible?•Would ECPE be possible?Would ECPE be possible?
26
fork() Sample3#include <iostream.h>#include <iostream.h>#include <unistd.h>#include <unistd.h>
int main()int main(){ // main{ // main intint number = 0;number = 0; // Note “number” on stack// Note “number” on stack
if ( 0 == if ( 0 == fork()fork() ) { ) { cout << "PID: " << getpid()cout << "PID: " << getpid()
<< ” child process exiting with number = ”<< ” child process exiting with number = ”<< ++number << endl;<< ++number << endl;
} //end if} //end if cout << "PID: " << getpid()cout << "PID: " << getpid()
<< " exiting with number = “<< " exiting with number = “<< --number << endl;<< --number << endl;
} //end main} //end main
// // how many output lines, students?how many output lines, students?// Which will be the different values for “number”?// Which will be the different values for “number”?
27
fork() Sample3 Output[process] a.out[process] a.outPID: 5587 exiting with number = -1PID: 5587 exiting with number = -1PID: 5588 child process exiting with number = 1PID: 5588 child process exiting with number = 1PID: 5588 exiting with number = 0 PID: 5588 exiting with number = 0
28
fork() Sample4 –Getting Interesting#include <iostream.h>#include <iostream.h>#include <unistd.h>#include <unistd.h>
int main()int main(){ // main{ // main int number = 100; int number = 100; // Note “number” on stack// Note “number” on stack
if ( 0 == if ( 0 == fork()fork() ) { ) { cout << "PID: " << getpid()cout << "PID: " << getpid()
<< " 1st child, number = “<< " 1st child, number = “<< ++number << endl;<< ++number << endl;
} //end if} //end if if ( 0 == if ( 0 == fork()fork() ) { ) { cout << "PID: " << getpid()cout << "PID: " << getpid()
<< " 2nd child, number = “<< " 2nd child, number = “<< ++number << endl;<< ++number << endl;
} //end if} //end if cout << "PID: " << getpid()cout << "PID: " << getpid()
<< " exiting with number = “<< " exiting with number = “ << --number << endl;<< --number << endl;
} //end main} //end main
29
fork() Sample4 Output[process] a.out[process] a.outPID: 20543 exiting with number = 99PID: 20543 exiting with number = 99PID: 20544 1st child, number = 101PID: 20544 1st child, number = 101PID: 20545 2nd child, number = 101PID: 20545 2nd child, number = 101PID: 20545 exiting with number = 100PID: 20545 exiting with number = 100PID: 20544 exiting with number = 100PID: 20544 exiting with number = 100[process] PID: 20546 2nd child, number = 102[process] PID: 20546 2nd child, number = 102PID: 20546 exiting with number = 101PID: 20546 exiting with number = 101
had to enter CR-LFhad to enter CR-LF[process] [process]
30
fork() Sample5 –Interesting#include <iostream.h>#include <iostream.h>//#include <unistd.h>//#include <unistd.h>
void fork_sample()void fork_sample(){ // fork_sample{ // fork_sample pid_t pid1 = pid_t pid1 = fork()fork();; pid_t pid2 = pid_t pid2 = fork()fork();; pid_t pid3 = pid_t pid3 = fork()fork();; coutcout << " pid1 = " << pid1<< " pid1 = " << pid1
<< " pid2 = " << pid2<< " pid2 = " << pid2<< " pid3 = " << pid3<< " pid3 = " << pid3<< endl;<< endl;
} //end fork_sample} //end fork_sample
int main()int main(){ // main{ // main fork_sample();fork_sample(); exit( 0 );exit( 0 );} //end main} //end main
31
fork() Sample5 Output[process] a.out[process] a.outpid1 = 24583 pid2 = 24584 pid3 = 24585pid1 = 24583 pid2 = 24584 pid3 = 24585pid1 = 24583 pid2 = 24584 pid3 = 0pid1 = 24583 pid2 = 24584 pid3 = 0pid1 = 24583 pid2 = 0 pid3 = 24587pid1 = 24583 pid2 = 0 pid3 = 24587pid1 = 0 pid2 = 24586 pid3 = 24588pid1 = 0 pid2 = 24586 pid3 = 24588[process] pid1 = 24583 pid2 = 0 pid3 = 0[process] pid1 = 24583 pid2 = 0 pid3 = 0pid1 = 0 pid2 = 24586 pid3 = 0pid1 = 0 pid2 = 24586 pid3 = 0pid1 = 0 pid2 = 0 pid3 = 0pid1 = 0 pid2 = 0 pid3 = 0pid1 = 0 pid2 = 0 pid3 = 24589pid1 = 0 pid2 = 0 pid3 = 24589had to enter CR-LFhad to enter CR-LF[process] [process]
32
fork() Sample6#include <iostream.h>#include <iostream.h>//#include <unistd.h>//#include <unistd.h>
void fork_sample()void fork_sample(){ // fork_sample{ // fork_sample pid_t pid1 = fork();pid_t pid1 = fork(); pid_t pid2 = fork();pid_t pid2 = fork(); pid_t pid3 = fork();pid_t pid3 = fork(); pid_t pid4 = fork();pid_t pid4 = fork(); printf( "I am %5d, parent= %5d,printf( "I am %5d, parent= %5d,
pid1= %5d, pid2= %5d, pid3= %5d, pid4= %5d\n”,pid1= %5d, pid2= %5d, pid3= %5d, pid4= %5d\n”, getpid(), getppid(), pid1, pid2, pid3, pid4 );getpid(), getppid(), pid1, pid2, pid3, pid4 );} //end fork_sample} //end fork_sample
int main()int main(){ // main{ // main fork_sample();fork_sample(); exit ( 0 );exit ( 0 );} //end main} //end main
33
fork() Sample6 Output
I am 22255, parent= 21528, pid1= 22256, pid2= 22257, pid3= 22258, pid4= 22260I am 22255, parent= 21528, pid1= 22256, pid2= 22257, pid3= 22258, pid4= 22260I am 22260, parent= 22255, pid1= 22256, pid2= 22257, pid3= 22258, pid4= 0I am 22260, parent= 22255, pid1= 22256, pid2= 22257, pid3= 22258, pid4= 0I am 22256, parent= 22255, pid1= 0, pid2= 22259, pid3= 22261, pid4= 22264I am 22256, parent= 22255, pid1= 0, pid2= 22259, pid3= 22261, pid4= 22264I am 22258, parent= 22255, pid1= 22256, pid2= 22257, pid3= 0, pid4= 22265I am 22258, parent= 22255, pid1= 22256, pid2= 22257, pid3= 0, pid4= 22265I am 22264, parent= 22256, pid1= 0, pid2= 22259, pid3= 22261, pid4= 0I am 22264, parent= 22256, pid1= 0, pid2= 22259, pid3= 22261, pid4= 0I am 22257, parent= 22255, pid1= 22256, pid2= 0, pid3= 22263, pid4= 22268I am 22257, parent= 22255, pid1= 22256, pid2= 0, pid3= 22263, pid4= 22268I am 22261, parent= 22256, pid1= 0, pid2= 22259, pid3= 0, pid4= 22266I am 22261, parent= 22256, pid1= 0, pid2= 22259, pid3= 0, pid4= 22266I am 22265, parent= 22258, pid1= 22256, pid2= 22257, pid3= 0, pid4= 0I am 22265, parent= 22258, pid1= 22256, pid2= 22257, pid3= 0, pid4= 0I am 22259, parent= 22256, pid1= 0, pid2= 0, pid3= 22262, pid4= 22267I am 22259, parent= 22256, pid1= 0, pid2= 0, pid3= 22262, pid4= 22267I am 22266, parent= 22261, pid1= 0, pid2= 22259, pid3= 0, pid4= 0I am 22266, parent= 22261, pid1= 0, pid2= 22259, pid3= 0, pid4= 0I am 22263, parent= 22257, pid1= 22256, pid2= 0, pid3= 0, pid4= 22270I am 22263, parent= 22257, pid1= 22256, pid2= 0, pid3= 0, pid4= 22270I am 22268, parent= 22257, pid1= 22256, pid2= 0, pid3= 22263, pid4= 0I am 22268, parent= 22257, pid1= 22256, pid2= 0, pid3= 22263, pid4= 0I am 22269, parent= 22262, pid1= 0, pid2= 0, pid3= 0, pid4= 0I am 22269, parent= 22262, pid1= 0, pid2= 0, pid3= 0, pid4= 0I am 22270, parent= 22263, pid1= 22256, pid2= 0, pid3= 0, pid4= 0I am 22270, parent= 22263, pid1= 22256, pid2= 0, pid3= 0, pid4= 0I am 22267, parent= 22259, pid1= 0, pid2= 0, pid3= 22262, pid4= 0I am 22267, parent= 22259, pid1= 0, pid2= 0, pid3= 22262, pid4= 0I am 22262, parent= 22259, pid1= 0, pid2= 0, pid3= 0, pid4= 22269I am 22262, parent= 22259, pid1= 0, pid2= 0, pid3= 0, pid4= 22269
34
fork() Sample6 Graph
59
67 62
69
57
68 63
70
55
56 58
64
28
60
66
6561
35
Command execve() So why does the So why does the fork()fork() command exist, if all it does command exist, if all it does
is: make a copy of the current process?is: make a copy of the current process? fork()fork() is just the first step of creating new is just the first step of creating new
processes, including the execution of any Unix processes, including the execution of any Unix commands, or programs, such as commands, or programs, such as a.outa.out
Therefore, code and data space have to be replaced Therefore, code and data space have to be replaced to spawn off a real non-shell processto spawn off a real non-shell process
Unix command Unix command execve()execve() accomplishes this accomplishes this A clever resource saving: pages in memory are not A clever resource saving: pages in memory are not
duplicated for new process; only modified pages are: duplicated for new process; only modified pages are: AKA AKA copy-on-writecopy-on-write
Side-effect of any Side-effect of any fork()fork() command is eventual command is eventual execution of two returns or exits, namely of parent execution of two returns or exits, namely of parent and child process; correspondingly, and child process; correspondingly, execve()execve() command creates no new return or exitcommand creates no new return or exit
36
execve() Samplevoid fork_exec_sample( char * argv[], char * envp[] )void fork_exec_sample( char * argv[], char * envp[] ){ // fork_exec_sample{ // fork_exec_sample
pid_t pid = pid_t pid = forkfork(); // parent + child exist now(); // parent + child exist now
if ( 0 == pid ) {if ( 0 == pid ) { // strange order of: 0 == . . . // strange order of: 0 == . . .// this is thread through child process// this is thread through child processcout << “ run 'herb.o' program." << endl;cout << “ run 'herb.o' program." << endl;// must be complete path; a relative path is also OK// must be complete path; a relative path is also OKif ( if ( execveexecve( "/u/herb/progs/process/herb.o", argv, envp ) < 0 ) ( "/u/herb/progs/process/herb.o", argv, envp ) < 0 )
{{cout << "Aborting " << endl;cout << "Aborting " << endl;exit( 0 );exit( 0 );
} //end if} //end if} //end if} //end ifcout << "Ending process " << pid << endl;cout << "Ending process " << pid << endl;
} //end fork_exec_sample} //end fork_exec_sample
int main( int argc, char * argv[], char * envp[] )int main( int argc, char * argv[], char * envp[] ){ // main{ // main
fork_exec_sample( argv, envp );fork_exec_sample( argv, envp );return 0;return 0;
} //end main} //end main
37
execve() Sample, uses herb.o// new program = process to be initiated by execve()// new program = process to be initiated by execve()// source named: herb.cpp// source named: herb.cpp#include <stdio.h>#include <stdio.h>int main()int main(){ // main{ // main printf( "<> SUCCESS <> You executed it\n" );printf( "<> SUCCESS <> You executed it\n" ); return 0;return 0;} //end main} //end main
1.1.Compile this, and rename: Compile this, and rename: a.outa.out --> --> herb.oherb.o2.2.Move Move herb.oherb.o into directory into directory /u/herb/progs/process/u/herb/progs/process
[process] a.out [process] a.out Ending process 21010Ending process 21010 run 'herb.o' program.run 'herb.o' program.[process] <> SUCCESS <> You executed it[process] <> SUCCESS <> You executed it
38
References1. IBM literature about Unix 8:
http://www.ibm.com/developerworks/aix/library/au-speakingunix8/
2. Computer Systems, a Programmer’s Perspective, Bryant and O’Halleron, Prentice Hall © 2011, 2nd ed.
3. Modern Operating Systems, Andrew S. Tanenbaum, Prentice Hall © 2011, second ed.
4. Operating System Concepts, Silberschatz and Galvin, Addison Wesley © 1998, fifth ed.
5. Posix Thread: https://computing.llnl.gov/tutorials/pthreads/#Thread
6. Thread, Hyperthread, Process: http://decipherinfosys.com/HyperthreadedDualCore.pdf http://decipherinfosys.com/HyperthreadedDualCore.pdf
7. Intel Hyperthreading: http://www.intel.com/technology/itj/2002/volume06issue01/vol6iss1_hyper_threading_technology.pdf