410 likes | 569 Views
Linux Multitasking. Linux process creation Linux Scheduler Linux Process Priority Normal Priority Real Time Priority. Linux programming. Linu x provides a set of API functions ( system calls) which may be called in a program to perform system specific functions.
E N D
Linux Multitasking Linux process creation Linux Scheduler Linux Process Priority Normal Priority Real Time Priority
Linux programming • Linux provides a set of API functions ( system calls) which may be called in a program to perform system specific functions. • These API functions allow us to directly: • Determine system configuration and user information • Manage and manipulate components such as devices, files, processes • Perform inter-process communication • Network communication • So we want to write programs which exhibit real-time features using these functions.
Linux APIs • Most Linux APIs access Unix’s kernel internal resources • When a user’s process invokes such API, context switching occurs. ie: user mode > kernel mode • Kernel mode is the CPU mode that the Unix kernel runs in. In this mode, the CPU has unrestricted access to all system resources ( including disks, memory, etc.). The CPU usually enters kernel mode during system calls and during the normal time slicing operations of the Unix Operating system. • A user context access only the process specific data, but a kernel context allows the process to access everything
API common characteristics • Most return an integer value to indicate termination status of execution: • A failure returns a -1 and the global value errno is set with an error status code which can be diagnosed( the code are defined in <errno.h>,and are usually refered when issuing the man command) • A successful execution returns either with 0 value or a pointer to some data record where the user-requested information is stored.
Unix process / task • A process in Unix is an instance of an executing program. It is either called a task/process. A process can create new processes. • The shell for instance is a process created when a user logs on and it creates new process/processes in response to a command. • For example: • % cat file 1: creates a new process and then run the “cat” command with the input parameter “file 1” • % ls | wc -1: creates 2 concurrent processes, with a pipe connecting the two processes. (list pipe word count -1)
Unix task / process • The ability to create and manipulate concurrent processes in Unix allows it to serve multiple users and perform multiple tasks concurrently. • Process creation and management is very important. • We need to understand how these are done.
A process data structure 0 Per process region table File Descriptor Table Current Directory Current Root Process limit parameters Code 253 Data Stack Per process U-area A Process Process Table (keeps info of al active process)
A process consists of … • Each process has its own address space which consists of: • Code/text segment – machine executable code format, a number of processes may share common code segment. • Data segment – consist of the and global variables, initialized and uninitialized values (may extend/shrink) • Stack segment- holds runtime stack of the user process, i.e storage for function arguments, automatic variables, return addresses.
The kernel has… • A process table: • Keeps track of all active processes, some belong to itself ( system processes) and others belong to users. • Each entry in the table contains pointers to the code, data, stack and the U-area of each process. • The U-area is an extension of the process table entry and contains other process specific data such as file descriptor table, information about current root directory, current working directory and a set of system imposed process resource limits, etc.
View of processes 0 Process A 253 Process B Process Table (keeps info of al active process) Process C
Process Attributes • The various attributes help the kernel to run and schedule the processes, maintain the security of the file system and so on. • Examples: • pid – process id, a non negative integer to identify a process. At anytime, a pid is unique Pid 0 is the scheduler process and pid 1 is /etc/init process which is the mother of all processes. • gid – group id, an integer to indicate to which group a process belongs. Useful when a process wants to signal all processes that share the same group id, eg. When logging out. To remain alive after logging out, a started process may set its default gid to a new gid. • environment – the environment of a process is a collection of null terminated strings represented as a null terminated array of character pointers, eg. HOME=/, LOGNAME= norbik, SHELL=/bin/sh etc. • pwd – present working directory, by default aprocess is placed in the same directory as its parent.
…/Process attributes • File size limits: normally there is a per-process limit on the size of a file that can be created with the write system call. This limit can be changed only by the superuser using ulimit system call. • Process priorities: the system also determines the proportion of CPU time a particular process is allocated partly on the basis of an integer value called nice (ranges typically from 0 to 39),where the higher the value the lower is the priority). Only the superuser can increase his priority using nice(-n); system call.
APIs on process attributes • Generally we have: • APIs which query the attributes • APIs which change the attributes • Some attributes can only be queried and not changed (eg: process ID), while a few att. Cannot be queried but can be changed (eg. Session ID)
Process attributes query APIs • getpid(), getppid() – returns the current process pid and parent’s pid, no argument is needed for the call • getuid(), getgid() - returns the calling process’s real user ID and real group ID, ie. The user ID and group id of the person who created the process, for eg. After logging in the shell started will have the real user ID and group ID of the person. These help to trace which user created which process. • geteuid(), getegid() – returns the effective user ID and effective group ID of the calling process. Used to determine the file access permission of the calling process.
System calls for task/process • Can be grouped into the following classes: • Task management, examples • Create a task, • Destroy a task • Ask info about a task • Modify attributes of a task • Task communication and synchronization
Process creation and manipulation • The most important system calls are: • fork: create a new process by duplicating the calling process. • exec: a family of system calls, which transform a process by overlaying its memory space with a new program. The different exec calls differ in argument list construction.
Process creation and manipulation • wait: this call provides process synchronization. It allows one process to wait until another related process finishes. • exit: used to terminate a process.
Task Creation: fork() • In Unix, a task is created by another task (parent task). This is done by the fork() system call. • Usage prototype: int pid; ….. pid = fork(); /* no argument */ • Kernel creates a new process which is called the ‘child’, and the one that issue the fork is call the parent. • After the fork call, both the parent and the child run concurrently, and execution in both resumes from the instruction just after the fork call.
..fork() pid= fork(); AFTER pid= fork(); Child BEFORE pid= fork(); Parent
…/fork() • A fork call may: • Succeed: the child PID is returned to the parent and the child receives a zero return value • Fail: no child process is created and errno is set with an error code value and value -1 is returned to the parent. • Failure may be due to insufficient memory ( errno= ENOMEM) to create anew process, or process number limit is reached (errno= EAGAIN) so try later.
…/fork() main() { int pid1; // holds process id in parent printf(“Just one process so far\n”); printf(“Calling fork…\n”); pid1 =fork(); if (pid1 == 0) printf(“I am the child \n”); else if (pid1 >0) printf ( “I am the parent, my child pid is %d\n”, pid1); else printf(“Error ; fork fails to create process\n”); }
Typical Output Just one process so far Calling fork… I am the child process I am the parent process, my child has pid1 = 4568 _______________________________________ Just one process so far Calling fork… I am the parent process, my child has pid1 = 4568 I am the child process
…/fork() code 100 data stack parent 253 code data stack Process table child Note: fork() copies also a memory area known as the 'U Area' (or User Area). This area contains, amongst other things, the file descriptor table of the process. This means that after returning from the fork() call, the child process inherits all files that were open in the parent process. If one of them reads from such an open file, the read/write pointer is advanced for both of them. On the other hand, files opened after the call to fork() are not shared by both processes. Further more, if one process closes a shared file, it is still kept open in the other process.
Differences between parent and child • PID number: must be unique • PPID number • Pending signals: set of signals pending delivery to the parent. They are reset to none in the child • Alarm clock time: it is 0 in the child • File locks: set of locks owned by the parent is not inherited by the child
Process overlay: exec() • A process may replace its current code, data, stack with those of another executable by using one of the “exec()” family of system calls. When a process executes an “exec()” system call, its PID and PPID numbers stay the same – only the code that the process is executing changes. The “exec()” family works like this la!
exec() family of Sys call int execl ( const char* path, const char* arg0,const char* arg1…const char* argn, NULL) int execlp ( const char* path, const char* arg0,const char* arg1…const char* argn, NULL) int execv (const char* path, const char* argv[]) int execvp (const char* path, const char* argv[])
Based on parameter specified in exec/l/v Old one is completely rub off but same pid …/ exec() • “exec” transform the calling process by loading a new program into its memory space. • If successful, the calling program is completely overlaid by the new program. • The new program is started from the beginning (unlike in fork() where control resumes from the fork invocation). • The result is like executing a new process, but the process id is not changed, so in fact it is NOT a new process to Unix. • A successful exec() never returns, while a failing exec() returns a -1.
Differentiating the exec s sys call • execl() is identical to execlp(), while • execv() is identical to execvp() • On the other hand execv() and execl () requires the absolute or relative file name to be supplied while the other two with the p at the back uses the $PATH environment variable to find path.
…./exec() family explanation • execl() and execlp() invoke the executable with the string arguments pointed to by arg1 through argn. arg0 must be the name of the executable file itself, and the list of arguments must be null terminated. • The execv() and execvp() invoke the executable with the string arguments pointed to by argv[1] to argv[n+1], where argv[n+1] is NULL. argv[0] must be the name of the executable itself.
…/ execl() main() { /* run ls –using “execl to run ls*/ printf (“Start executing ls…\n”); execl(“/bin/ls”,”ls”,”-1”,(char *) 0); /* if execl returns, then the call has failed, so…*/ printf(“Erro:execl fails to run ls\n”0); }
../ typical output Start executing ls… (* followed by a detail listing of files in the current directory *) OR…. Start executing ls… Error: execl fails to run ls
…/execv() main() { /* run ls –using “execv to run ls*/ char *av[3]; av[0] =“ls”; av[1]= “-1”; av[2] = (char *) 0; printf (“Start executing ls using execv…\n”); execv(“/bin/ls”,av); /* if execv returns, then the call has failed, so…*/ printf(“Erro:execv fails to run ls\n”0); }
…/execv() Start executing ls using execv… (* followed by a detail listing of files in the current directory *) OR…. Start executing ls using execv… Error: execv fails to run ls
Combining fork and exec • Concurrent programming under unix can be established through the utilization of both fork and exec together. • By forking and then exec in the child process, a process creates a concurrent sub –process which then runs another program. eg the shell executes each user command by calling fork and exec to execute the requested command in a child process. • Advantages: • A process can create multiple processes to execute multiple programs concurrently • Since each child has its own virtual address space, the parent is not affected by the execution status of its child.
…/ fork & execl AFTER EXCEL pid= fork(); pid= fork(); child /* first line of ls*/ BEFORE FORK pid= fork(); pid= fork(); parent AFTER FORK
…/fork & execl main() { /* runls3 – run ls as a child process */ int pid; pid = fork(); if ( pid > 0 ) /* in the parent process */ { wait(); printf(“ls is completed\n”); exit(0); } else if (pid ==0) { /* in the child process */ execl(“/bin/ls”,”ls”,”-1”,(char *)0); printf(“Error:execl fails to run ls\n”); } else printf(“Error : fork fails to create process\n”);
Typical output: fork & execl (* a detail listing of files in the current directory *) ls is completed ___________________________________ Error: execl fails to run ls ls is completed ___________________________________ Error: fork fails to create process
wait • Usage: int retval,status; • Retval=wait&(status); • Used to temporarily suspends exe. Of a process while its child process is still running. Once the child is finished, the waiting parent is restarted. • So, wait is a system call to synchronize between processes or for a parent to know execution status of its child. • The return value of a wait is usually the child’s process id. • The argument to wait can be just a null pointer or address of an integer which will give useful information when wait returns.
sleep • Usage: int retval; • retval = sleep (duration ); • Makes the scheduler pre-empts the process and it goes into a waiting state ( on a specified amount of time) • After the “duration” seconds it will be put in ready state. • From the real –time perspective, it will take atleast “duration” seconds, but it may be longer. This is because, Unix being a shred environment cannot guarantee the fulfillment. • In a proper RT-kernel, we can force that to happen using a certain kind of priority mechanism.
exit • Usage: int status; • exit(status); • Used to terminate process. Note a process also terminates naturally when the end of the program is reached or when the main function issues a return. • But exit has other side effects: • All open file descriptors are closed; • If parent has executed a wait call, it will be restarted; • Clean up action (buffering in stdio), ie: data, stack and u-area to be deallocated • “status” returns 0 on success, a non-zero otherwise.