Presentation is loading. Please wait.

Presentation is loading. Please wait.

Real Time Programming Tech.

Similar presentations


Presentation on theme: "Real Time Programming Tech."— Presentation transcript:

1 Real Time Programming Tech.
Process Creation in Linux Real Time System

2 Real Time Programming Tech.
Real time means a program must be able to respond to events it its environment by the specified deadline. Quest How does program response to event Polling Interrupt

3 Poll Issue response time depends very much on where the program is executing when the event occur. no priority level

4 Interrupt Most modern processors implement three distinct types of interrupt: ■ The INT instruction, sometimes called a TRAP. This is like a subroutine call. ■ Processor exceptions. Fault conditions like divide by 0 or illegal memory reference can be handled through the interrupt mechanism. These two forms of interrupt are synchronous with respect to instruction execution. That is, INT is an instruction and fault exceptions are the direct result of instruction execution. The third type of interrupt is generated by events that occur external to the processor. These are generated by the input / output hardware and occur asynchronously with respect to instruction execution.

5 Example from: Linux for Embedded Real Time Application
Example of asynch. Int. A DAQ system We have system which takes reading of all channels and interrupts the processor. The ISR would then read the data and store to buffer which can be later read by the background main program. Assume to ensure data validity we feed the same cont. varying signal to channel 5 and 6. We would assume that the program would never fail since both read identical signal. Example from: Linux for Embedded Real Time Application

6 Example from: Linux for Embedded Real Time Application
Analysis of Soln In fact, the program as written is guaranteed to fail Because an interrupt can occur between the update of Cur_temp and the update of Set_temp with the result that the value for Cur_temp comes from the previous data set while the value for Set_temp comes from the current data set. Since the input signal is varying over time and the two data sets are separated by a finite time, the values will be different and the program will fail. This then is the essence of the real-time programming problem; managing asynchronous interrupts so they don’t occur at inopportune times. There is a simple, albeit inelegant, solution to the problem. We can put a Disable Interrupt (CLI) instruction before the update of Cur_temp and an Enable Interrupt (STI) instruction after the update of Set_temp. This prevents the interrupt from interfering with the variable updates. It turns out that judicious use of STI and CLI is a key element of the “correct” solution but simply scattering STI and CLI throughout the code is like using go to’s or global variables. It’s just asking for trouble. Example from: Linux for Embedded Real Time Application

7 The right approach The “correct” solution is called multitasking, which has proven to be a powerful paradigm for structuring real-time, interrupt-driven systems. The basic idea is that we can break a large problem down into a bunch of smaller, simpler problems. Each one of these sub-problems becomes a task. Each task does one thing to keep it simple. Then we pretend that all of these tasks are running in parallel. They aren’t really running in parallel (running at the same time) less you have a multiprocessor system. On a single processor the tasks execute concurrently (progressing at the same time)

8 Task Task is conceptual In Linux  Task is a process

9 Process in Linux Each process is identified by its process id (pid) and allocates process space in the main memory. To perform multiprogramming on a uniprocessor system, each running process is allocated at a fixed time slice (round robin) to run on a processor. Once the time slice is over, it will come back to the scheduler queue to run again in order to execute the remaining code In Linux, the processes are dependent. init (pid = 1) is the first process. Try out the pstree command. Once the process is completed, the exit status should be given to its parent process. If the parent is busy with some other activities, then the kernel de-allocates all the child resources and puts it into the zombie state. The child process is terminated after the parent collects its exit status. Suppose the parent exits before completion of a child process, then the child will become an orphan process and init will take care of it. In Linux, the fork system call is used to create a child process.

10 Technically how do we create and manipulate process?
Ready…..

11 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

12 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.

13 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.

14 Task Creation: fork() In Linux, a process is created by another process (parent process). 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.

15 ..fork() pid= fork(); AFTER pid= fork(); Child BEFORE pid= fork();
Parent

16 ….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.

17 …/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”); }

18 Typical Output Just one process so far Calling fork…
I am the child process I am the parent process, my child has pid1 = 4568 _______________________________________

19 …/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.

20 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

21 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!

22 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[])

23 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.

24 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.

25 …./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.

26 …./execl() execl(“/bin/ls,… AFTER run ls program
/* first line of ls */ BEFORE ls command

27 …/ execl() main() { /* run ls –using “execl to run ls*/
printf (“Start executing ls…\n”); execl(“/bin/ls”,”ls”,”-l”,(char *) 0); /* if execl returns, then the call has failed, so…*/ printf(“Erro:execl fails to run ls\n”0); }

28 ../ typical output Start executing ls…
(* followed by a detail listing of files in the current directory *) OR…. Error: execl fails to run ls

29 …/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); }

30 …/execv() Start executing ls using execv…
(* followed by a detail listing of files in the current directory *) OR…. Error: execv fails to run ls

31 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.

32 …/ fork & execl AFTER EXCEL pid= fork(); pid= fork(); child
/* first line of ls*/ BEFORE FORK pid= fork(); pid= fork(); parent AFTER FORK

33 …/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”);

34 Typical output: fork & execl
(* a detail listing of files in the current directory *) ls is completed ___________________________________ Error: execl fails to run ls Error: fork fails to create process

35 wait() Usage: int retval,status;
retval=wait&(status); Used to temporarily suspends execution 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.

36 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.

37 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.

38 Run all the programs given in these notes and make sure they all work.


Download ppt "Real Time Programming Tech."

Similar presentations


Ads by Google