lecture 5 process, thread and task september 22, 2015 kyu ho park
TRANSCRIPT
5
Process Concept
An operating system executes a variety of programs: Batch system – jobs Time-shared systems – user programs or
tasks Process – a program in execution; process
execution must progress in sequential fashion A process includes:
program counter stack data section
Virtualization
9
Processes are provided with 2 virtualizations:
• Virtualized Processor• Virtualized Memory
10
Process State
As a process executes, it changes state new: The process is being created running: Instructions are being executed waiting: The process is waiting for some
event to occur ready: The process is waiting to be
assigned to a process terminated: The process has finished
execution
11
Diagram of Process State
terminated
runningready
new admitted
waiting
interrupt
scheduler dispatch
I/O or event waitI/O or event completion
exit
12
Process Control Block (PCB)Information associated with each
process Process state Program counter CPU registers CPU scheduling information Memory-management information Accounting information I/O status information
13
Process management
RegistersProgram counterProgram status wordStack pointerProcess stateTime when process startedCPU time usedChildren’s CPU timeTime of next alarmMessage queue pointersPending signal bitsProcess idVarious flag bits
Memory management
Pointer to text segmentPointer to data segmentPointer to bss segmentExit statusSignal status Process idParent processProcess groupReal uidEffectiveReal gidEffective gidBit maps for signalsVarious flag bits
Files management
UMASK maskRoot directoryWorking directoryFile descriptorsEffective uidEffective gidSystem call parametersVarious flag bits
Some of the fields of the MINIX process table
Process Control Block(PCB)
14/39
Process Descriptor Overview of the Linux Process Descriptor ( struct
task_struct )
This seminar (chapter 3) focus on Process State
TASK_RUNNING TASK_INTERRUPTIBLE TASK_UNINTERRUPTIBLE TASK_STOPPED TASK_TRACED TASK_ZOMBIE EXIT_DEAD
Process parent/child Relationship
Process DescriptorProcess SwitchingCreating ProcessesDestroying Processes
Task List Representation of a process: A process
descriptor of the type struct task_struct //<linux/sched.h>1.7KBytes on a 32-bit machine
Task list: A circular doubly linked list of task_struct
15
16
CPU Switch From Process to ProcessP 0
Save state into PCB0
reload from PCB1
Save to PCB1
Reload from PCB0
OS P 1
idle
17
Operations on Processes: Process Creation Parent process create children processes,
which, in turn create other processes, forming a tree of processes
Possibilities of Resource sharing Parent and children share all resources Children share subset of parent’s
resources Parent and child share no resources
Possibilities of Execution Parent and children execute concurrently Parent waits until children terminate
18
Process Creation (Cont.) Possibilities of Address space
Child duplicate of parent Child has a program loaded into it
UNIX examples fork system call creates a new
process exec system call used after a fork
to replace the process’ memory space with a new program
fork()
19
Initial Process
fork()
Returns a new pid(child process)
Returns zero
Original ProcessContinues
New Process:Child
20
fork()
Stack
Heap
BSS
Data
Text . fork( ).
SP PC .
.
open files
.
.
Registers
Resources
pid=1000
ID
Stack
Heap
BSS
Data
Text . fork( ).
SP PC .
.
open files..
Registers
Resources
pid=1001
ID
Stack
Heap
BSS
Data
Text . fork( ).
SP PC .
.
open files
.
.
Registers
Resources
pid=1000
ID
ParentChild
PC
PCPC
fork()int main(){
int i;for(i=0; i<10; i++){
printf(“Process_id=%d, i=%d\n”, getpid(), i);
if(i==5){printf(“Process_id=%d: fork() to start\
n”,getpid());int forkValue=fork();printf(“forkValue=%d\n”, forkValue);
}}
}
24
Creation of a process
26
•fork() system call : It creates a new process by duplicating an existing one. The process that calls fork() is the parent, and the new process is the child.•pid = fork();• in the parent process, pid is the child process ID and in the child process, pid=0;
•execve() system call : It creates a new address space and load a new program into it.
int execve(const char *filename, char *const argv[],
char *const envp[]);argv: command line argument;envp: path name, etc;
32
Process Termination Process executes last statement and asks the operating
system to delete it (exit) Output data from child to parent (via wait) Process’ resources are deallocated by operating
system Parent may terminate execution of children processes
(abort) Child has exceeded allocated resources Task assigned to child is no longer required If parent is exiting
Some operating system do not allow child to continue if its parent terminates
All children terminated - cascading termination
Duplicating a process image#include <sys/types.h>#include <unistd.h>pid_t fork(void);
-return vaule of fork() : pid of the child if successful to the parent, 0 to the child.
If failed, -1 to the parent.-unistd.h : fork() prototype is defined.-types.h : pid_t is defined.
34
fork()1. #include <unistd.h>2. #include <sys/types.h>3. #include <stdio.h>4. #include <stdlib.h>5. main()6. { pid_t pid;7. printf("Start!\n");8. pid = fork();9. if( pid == 0) printf("I am the Child !\n");10. else if (pid > 0) printf("Parent pid=%d,
Child pid=%d\n", (int)getpid(),pid);11. else printf("fork() failed!\n");}
35
1. #include <unistd.h>2. #include <sys/types.h>3. #include <stdio.h>4. #include <stdlib.h>5. main()6. { pid_t pid;7. printf("Start!\n");8. pid = fork();9. if( pid == 0) printf("I am the Child !\n");10. else if (pid > 0) printf("Parent pid=%d,
Child pid=%d\n", (int)getpid(),pid);11. else printf("fork() failed!\n");}
1. #include <unistd.h>2. #include <sys/types.h>3. #include <stdio.h>4. #include <stdlib.h>5. main()6. { pid_t pid;7. printf("Start!\n");8. pid = fork();9. if( pid == 0) printf("I am the Child !\n");10. else if (pid > 0) printf("Parent pid=%d,
Child pid=%d\n", (int)getpid(),pid);11. else printf("fork() failed!\n");}
Original process
Parent process Child process
PC
PC+1 PC+1
pid ==0pid > 0
Replacing a process image#include <unistd.h>
char **environ;
int execl(const char *path, const char *arg0, …,(char *)0);int execlp(const char *file, const char *arg0,…,(char *)0);int execle(const char *path, const char *arg0,…,(char *)0,char *const envp[]);int execv(const char *path, char *const argv[]);int execvp(const char *file, char *const argv[]);int execve(const char *path, char *const argv[],char *const envp[]);
36
Examples of exe*()#include <unistd.h>char *const ls_argv[]={“ls”,”-l”,0};
char *const ls_envp[]={“PATH=bin:/usr/bin”,”TERM=console”,0};
execl(“/bin/ls”,”ls”,”-l”,0);execlp(“ls”,”ls”,”-l”,0);execle(“/bin/ls”,”ls”,”-l”,0,ls_envp);execv(“/bin/ps”,ls_argv);execvp(“ls”,ls_argv);execve(“/bin/ls”, ls_argv, ls_envp);
37
Waiting for a process#include <sys/types.h>#include <sys/wait.h>
pid_t wait(int *status);
The parent process executing wait(), pauses until its child process stops. The call returns the pid of the child process
38
status status: it is the value transferred to
the parent by exit(int status).
39
Parent process: wait(&status)
Child process: exit(1);
0x00 0x00 0x64 0x00
0x00 0x00 0x00 0x64
exit(1)root@ubuntu:~/Test/FORK# ./forkwaitStart!Parent pid=25820, Child pid=25821I am the Child !status=256
If(pid !=0){int stat;pid_t pid_child;pid_child = wait(&status);printf(“Child has
finished,pid_child=%d\n”,pid_child);if(status !=0) printf(“Child finished normally\n”);else printf(“Child finished abnormally\n”);
}
40
41
#include <unistd.h>#include <sys/types.h>#include <stdio.h>#include <stdlib.h>
main(){ pid_t pid; int status;
printf("Start!\n");
pid = fork();
if( pid == 0) { printf("I am the Child !\n"); exit(100); } else if (pid > 0){ printf("Parent pid=%d, Child pid=%d\n", (int)getpid(),pid); wait(&status); printf("status=%d\n", status); }
else printf("fork() failed!\n");}
root@ubuntu:~/Test/FORK# ./forkwaitStart!Parent pid=25789, Child pid=25790I am the Child !status=25600root@ubuntu:~/Test/FORK# vi forkwait.c
./forkwait
forkwait.c
exit()#include <stdlib.h>void exit(int status);
/*Terminating current process and transfer the status to the parent.The value of status ranges from 0 to 255 integer value. */
42
waitpid( )#include <sys/types.h>#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
pid : pid of the child,status : transferred from the child executing exit(status),options 0 : usual wait state, that is , the parent waits until the child process finishes, WNOHANG :the parent process does not stay at ‘wait’ state.
43
Zombie Processes
44
Terminated
runningready
new admitted
waiting
interrupt
scheduler dispatch
I/O or event waitI/O or event completion
exit
TTerminated
Exit_Zombie
Wait( )
47
Threads
47
•So far a process is a single thread of execution.
•The single thread of control allows the process to perform only one task . The user cannot simultaneously type in characters and run the spell checker with the same process.
•Therefore modern OSs have extended the process concept to allow a process to have multiple threads of execution.
48
Programcounter
Thread
Process
Computer
Computer
(a) (b)
(a)Three processes each with one thread. (b)One process with three threads.
Process and Threads
Linux Implementation of Threads
In the Linux, each thread has a unique task_struct . Linux implements all threads as standard processes.
A thread in Linux is just a process that shares certain resources( such as an address space).
50
52
Sharing of threads
open files
.
.
SP PC .
.
Registers
Resources
Stack1
Heap
BSS
Data
Stack2
Text
SP PC .
.
Registers
Thread1
Thread2
Creating Threads: clone( )#include <sched.h>
int clone( int (*func)(void *), void *child_stack, int flags, void *func_arg,…);
/*The caller must allocate a suitably sized block in the argument child_stack. The stack grows downward, so the child_stack argument should point to the high end of the allocated block.*/
int main(){ int child_stack[4096]; …. clone(thread_func, (void *)(child_stack+4095), CLONE_THREAD, NULL); …..
}int thread_func(void *arg){ ….}
53
If the flag is set to CLONE_CHILD_CLEARID|CLONE_CHILD_SETTID,the creates one is a process.
clone() example#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <linux/unistd.h>#include <sched.h>
int thread_func(void *arg){ printf("Child :TGID(%d), PID(%d)\n",(int) getpid(),(int) syscall(__NR_gettid)); sleep(1); return 0;}
int main(void){ int pid; int child_stack[4096];
printf("Start!\n"); printf("Parent:TGID(%d), PID(%d)\n",(int)getpid(),(int) syscall(__NR_gettid));
clone (thread_func, (void *)(child_stack+4095), CLONE_VM | CLONE_THREAD | CLONE_SIGHAND, NULL);
sleep(1);
printf("End!\n"); return 0;}
54
pthread example#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <linux/unistd.h>#include <pthread.h>
void *pthread_func(void *data){ int id; int i=0; pthread_t t_id; id = *((int *)data); printf(“I am the created pthread.\n”); sleep(2);}
int main(void){ int pid, status; int a = 1; int b = 2; pthread_t p_thread[2];
printf("Start!\n");
55
if((pid = pthread_create(&p_thread[0], NULL, pthread_func, (void*)&a)) < 0){ perror("Creation0 failed! "); exit(1); } if((pid = pthread_create(&p_thread[1], NULL, pthread_func, (void*)&b)) < 0){ perror("Creation1 failed"); exit(2); }
pthread_join(p_thread[0], (void **)&status); printf("pthread_join0\n");
pthread_join(p_thread[1], (void **)&status); printf("pthread_join1\n");
printf(“The Parent.\n”);
printf("End!\n"); return 0;}
Pthread and LinuxThread Thread got attention with the advent
of the POSIX 1003.c specification. But not so popular.
LinuxThreads which was very close to the POSIX standard: 1996 .
POSIX Thread: NPTL(Native POSIX Thread Library) NGPT(New Generation POSIX Threads)
57
NPTL
POSIX(Portable OS Interface)
UNIX
Drawbacks of thread program
Difficult to write multi-threaded programs.
Difficult to debug multi-threaded programs.
58
pthread functions#include <pthread.h>int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);void pthread_exit(void *retval);
Int pthread_join(pthread_t th, void **thread_return);//equivalent to wait( ).
59
pthread_create, exit, and join
60
pthread_create()
pthread_exit()
pthread_join()Master_thread
created_
threads
Task ?In Linux,
Processes and threads are all represented bytask_struct.
Every task has its own unique id and it is represented at pid field of <task_struct>.
But, according to the POSIX standard, all threads of a process shoud have the same pid.Linux adopts tgid(thread group id) to satisfy the POSIX standard.Therefore,a task if it is a process : pid == tgid,
if it is a thread : pid != tgid and the child’s tgid has the same tgid of the parent.
63
Simultaneous execution of threads
1. #include <stdio.h>2. #include <unistd.h>3. #include <stdlib.h>4. #include <pthread.h>
5. void *thread_function(void *arg);6. int run_now = 1;7. char message[] = "Hello World";
8. int main() {9. int res;10. pthread_t a_thread;11. void *thread_result;12. int print_count1 = 0;
13. res = pthread_create(&a_thread, NULL, thread_function, (void *)message);
14. if (res != 0) {15. perror("Thread creation failed");16. exit(EXIT_FAILURE);17. }
18. while(print_count1++ < 20) {19. if (run_now == 1) {20. printf("1");21. run_now = 2;22. }23. else {24. sleep(1);25. }26. }
64
1. printf("\nWaiting for thread to finish...\n");2. res = pthread_join(a_thread, &thread_result);3. if (res != 0) {4. perror("Thread join failed");5. exit(EXIT_FAILURE);6. }7. printf("Thread joined\n");8. exit(EXIT_SUCCESS);9. }
10. void *thread_function(void *arg) {11. int print_count2 = 0;
12. while(print_count2++ < 20) {13. if (run_now == 2) {14. printf("2");15. run_now = 1;16. }17. else {18. sleep(1);19. }20. }
21. sleep(3);22. }
semaphore#include <semaphore.h>int sem_init(sem_t *sem, int pshared, unsigned int value);- sem: points to a semaphore object, pshared: if 0, the semaphore is local to the current process, else the semaphore may be shared between processes(Linux does not support it). value: initial value of the semaphore.
int sem_wait(sem_t *sem);-This function waits until the semaphore is nonzero, and decreases the value of semaphore by 1.
int sem_post(sem_t *sem);-This function increases the value of the semaphore by 1.
int sem_destroy(sem_t *sem);
65
Synchronization with semaphore
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#include <semaphore.h>
void *thread_function(void *arg);sem_t bin_sem;
#define WORK_SIZE 1024char work_area[WORK_SIZE];
int main() { int res; pthread_t a_thread; void *thread_result;
res = sem_init(&bin_sem, 0, 0); if (res != 0) { perror("Semaphore initialization failed"); exit(EXIT_FAILURE); } res = pthread_create(&a_thread, NULL, thread_function, NULL); if (res != 0) { perror("Thread creation failed"); exit(EXIT_FAILURE); }
66
printf("Input some text. Enter 'end' to finish\n"); while(strncmp("end", work_area, 3) != 0) { fgets(work_area, WORK_SIZE, stdin); sem_post(&bin_sem); } printf("\nWaiting for thread to finish...\n"); res = pthread_join(a_thread, &thread_result); if (res != 0) { perror("Thread join failed"); exit(EXIT_FAILURE); } printf("Thread joined\n"); sem_destroy(&bin_sem); exit(EXIT_SUCCESS);}
void *thread_function(void *arg) { sem_wait(&bin_sem); while(strncmp("end", work_area, 3) != 0) { printf("You input %d characters\n", strlen(work_area) -1); sem_wait(&bin_sem); } pthread_exit(NULL);}