System Programming Lecture Note 5 Task Programming October

System Programming Lecture Note 5. Task Programming October 11, 2019 Jongmoo Choi Dept. of Software Dankook University choijm@dankook. ac. kr http: //embedded. dankook. ac. kr/~choijm

Objectives Understand task-related system calls Learn how to create a new task Learn how to execute a new program Discuss about shell (command interpreter) Understand issues on multitask Refer to Chapter 24, 27 in the LPI and Chapter 8 in the CSAPP 2

Introduction Task-related system calls ü Basic § § § ü fork(), clone() : create a task execve() : execute a new program (binary loading) exit() : terminate a task wait(), waitpid() : wait for a task’s termination (child or designated) getpid() : get a task ID Advanced § signal(), kill(), alarm() : signal handling such as register a signal catch function and signal delivery § sleep(), pause() : block for a certain period or until receiving a signal § nice(), getpriority(), setpriority() : control task priority § sched_setscheduler(), sched_getscheduler(), sched_setparam(), sched_getparam() : control task scheduling policy and parameters § times(), gettimeofday() : get timing information of a task and get the current time § ptrace() : allow a task to control the execution of other tasks 3

Task creation (1/6) fork() system call ü Make a new task whose memory image (text, data, …) is the same as the existing task § Existing task: parent task § New task: child task ü Split the flow control into two (system’s viewpoint) § One for parent and the other for child task ü Two return values (program’s viewpoint) § Parent task: child’s pid (always larger than 0) § Child task: 0 4

Task creation (2/6) Practice 1: making two control flows /* fork_test. c example, Sept. 26, choijm@dku. edu */ #include <sys/types. h> #include <unistd. h> #include <stdio. h> #include <stdlib. h> main() { The flow of control is divided here. pid_t fork_return; printf("Hello, my pid is %dn", getpid()); if ( (fork_return = fork()) < 0) { perror("fork error"); exit(1); } else if (fork_return == 0) { /* child process */ printf("child: pid = %d, ppid = %dn", getpid(), getppid()); } else { /* parent process */ wait(); printf("parent: I created child with pid=%dn", fork_return); } This message is printed out twice. } /* Following line is executed by both parent and child */ printf("Bye, my pid is %dn", getpid()); 5

Task creation (3/6) Practice 1: execution results 6

Task creation (4/6) Practice 2: variable (local and global) management /* fork_test 2. c: accessing variables, Sept. 26, choijm@dku. edu */ /* Note: This code is borrowed from “Advanced Programming in the UNIX Env. ” */ #include <unistd. h> #include <stdio. h> #include <stdlib. h> int glob = 6; char int main(void) { int buf[] = "a write to stdoutn"; var = 88; pid_t fork_return; if (write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf)) { perror(“write error”); exit(1); } printf("before forkn"); /* we don't flush stdout */ } if ( (fork_return = fork()) < 0) { perror("fork error"); exit(1); } else if (fork_return == 0) { /* child */ glob++; var++; /* modify variables */ } else sleep(2); /* parent */ printf("pid = %d, glob = %d, var = %dn", getpid(), glob, var); exit(0); 7

Task creation (5/6) Practice 2: execution results 8

Task creation (6/6) System’s viewpoint of fork() memory parent task data // task_struct pid = 15554 memory info. text glob, buf glob++; var++ var, pid stack child task glob, buf // task_struct pid = 15555 memory info. data stack var, pid address : protection barrier We can exploit “COW(Copy_on_Write)” for enhancing performance We do not consider “Paging” in this slide. 9

Task execution (1/7) execve() system call ü Execute a new program § Replace the current task’s memory image (text, data, stack) with new binary ü Six interfaces execlp execl Build argv execvp PATH prefix execle Build argv execv Environment Build argv execve Syntax int execlp(const char *filename, const char *arg 0, …, const char argn, (char *) 0); int execvp(const char *filename, char *const argv[ ]); int execl(const char *pathname, const char *arg 0, …, const char *argn, (char *) 0); int execv(const char *pathname, char *const argv[ ]); int execle(const char *pathname, const char *arg 0, …, const char *argn, (char *) 0, char *const envp[ ]); int execve(const char *pathname, char *const argv[ ], char *const envp[ ]); 10

Task execution (2/7) Practice 3: executing a new program (binary) /* execl_test. c: execute a hello program, Sept. 27, choijm@dku. edu */ #include <unistd. h> #include <stdio. h> #include <stdlib. h> int main(int argc, char *argv[]) { pid_t fork_return, d_pid; int exit_status = -1; } What does this comment mean? if ((fork_return = fork()) == -1) { // fork error handling } else if (fork_return == 0) { // child execl(". /hello", (char *)0); printf("Child. . I’m heren"); // if execl() succeeds, the above printf() is not performed!! exit(1); } else { // parent d_pid = wait(&exit_status); printf("Parent. . I’m heren"); printf("exit status of task %d is %dn", d_pid, exit_status); } 11

Task execution (3/7) Practice 3: execution results 12

Task execution (4/7) System’s viewpoint of execve() ü ü Replace memory image (text, data, stack) with new one The role of loader discussed in LN_chapter 1 printf("Child. . memory task I’m heren"); pid = 25150 data text stack text hello header text data …… data stack 13 env. , args. , initial stack, . .

Task execution (5/7) Practice 4: parameter passing to main() via shell /* execl_test 2. c: printing argv[] and env[], Sept. 27, choijm@dku. edu */ #include <stdio. h> int main(int argc, char *argv[], char *envp[]) { int i; for (i=0; argv[i]; i++) printf(“arg %d = %sn”, i, argv[i]); for (i=0; envp[i]; i++) printf(“env %d = %sn”, i, envp[i]); } 14

Task execution (6/7) Practice 5: parameter passing to main() via execle() /* execle_test 3. c: parameter passing, Sept. 27, choijm@dku. edu */ #include <sys/types. h> #include <unistd. h> #include <stdio. h> #include <wait. h> int main(int argc, char *argv[]) { pid_t fork_return, d_pid; int exit_status; char *const myenv[] = {"sys programming", "is", "fun", (char *)0}; } if ((fork_return = fork()) == -1) { // fork error handling } else if (fork_return == 0) { // child execle(". /execl_test 2", “Hi", “DKU", (char *)0, myenv); printf("Child. . I’m heren"); // if execl succeeds, this printf() is not carried out!! } else { // parent d_pid = wait(&exit_status); printf(“exit pid = %d with status = %dn", d_pid, WEXITSTATUS(exit_status)); } 15

Task execution (7/7) Practice 5: execution results 16

Binary format (1/2) ELF (Executable Linking Format) Fig. 7. 11 Typical ELF executable object file Fig. 7. 3 Typical ELF relocatable object file (Source: computer systems: a programmer perspective) Why we separate data into two sub-regions (initialized data and bss)? 17

Binary format (2/2) Real view in Linux 18

Shell (1/5) Command interpreter ü Execute commands requested by users Basic logic ü ü ü display prompt, input parsing for external commands: do fork() and execve() at child task for internal commands: perform in shell without fork() and execve() Advanced functions ü ü Prompt ($) Background processing Redirection Pipe (fork twice) Shell script input/parsing fork child processing execve processing waiting 19

Shell (2/5) Sample example /* Simple shell, Kyoungmoon Sun(msg 2 me@msn. com), */ /* Dankook Univ. Embedded System Lab. 2008/7/2 */ #include <unistd. h>. . . tokens[0] = “cat” tokens[1] = “alphabet. txt” or bool cmd_help( int argc, char* argv[]) { tokens[0] = “gcc”. . . tokens[1] = “-o” } = “hello” int tokenize( char* buf, char* delims, char* tokens[], int max. Tokenstokens[2] ){ tokens[3] = “hello. c”. . . token = strtok( buf, delims ); while( token != NULL && token_count < max. Tokens ) {. . . } } bool run( char* line ) {. . . token_count = tokenize( line, delims, tokens, sizeof( tokens ) / sizeof( char* ) ); // handling internal command such as cd, stty and exit // handling redirection, pipe and background processing if( (child = fork()) == 0 ) { execvp( tokens[0], tokens ); } wait (); . . . same as execlp(“cat”, “alphabet. txt”, (char *)0); } int main() { char line[1024]; while(1) { $ cat alphabet. txt printf( "%s $ ", get_current_dir_name() ); or fgets( line, sizeof( line ) - 1, stdin ); $ gcc –o hello. c if( run( line ) == false ) break; }. . . 20 }

Shell (3/5) Execution example 21

Shell (4/5) Background processing ü ü both shell and command run concurrently how to: do not use wait() Redirection ü ü read/write data from/to file instead of STDIN/STDOUT how to: replace STDIN/STDOUT with file’s fd using dup 2() before execve() ( refer to LN 3) pipe ü ü create two tasks and make them communicate via pipe how to: replace STDIN/STDOUT with fd[0]/fd[1] using pipe() and dup 2() before execve() 22

Shell (5/5) pipe() example ü One of IPC (Inter Process Communication) mechanisms 23

Issues on multitask (1/6) Until now ü ü We learned about the task structure, fork(), and execve() We can create multiple tasks and run multiple programs Multiple tasks raise several issues ü ü ü ü Scheduling Memory management IPC (Inter Process Communication) Race condition and Synchronization Context switch thread … 24

Issues on multitask (2/6) Race condition /* Race condition example by choijm. From Advanced Programming in UNIX Env. */ #include <sys/types. h> #include <unistd. h> static void charatatime(char *str) { int i; } for (; *str; str++) { for (i=0; i<1000; i++); write(STDOUT_FILENO, str, 1); } int main(void) { pid_t pid; } if ( (pid = fork()) < 0) { perror("fork"); exit(1); } else if (pid == 0) { charatatime("output from childn"); } else { charatatime("output from parentn"); } 25

Issues on multitask (3/6) When two tasks run concurrently /* virtual_address. c: printing memory address , Oct. 9, choijm@dku. edu */ int glob 1, glob 2; main() { int m_local 1, m_local 2; Virtual address printf("process id = %dn", getpid()); printf("main local: nt%p, nt%pn", &m_local 1, &m_local 2); printf("global: nt%p, nt%pn", &glob 2, &glob 1); } while (1); 26

Issues on multitask (4/6) When two tasks run concurrently (cont’) stack text for task B data for task A heap bss data text Address space for Task A segment table or page table text for task A data for task B physical memory 27 bss data text Address space for Task B

Issues on multitask (5/6) Thread: programming example // fork example // by J. Choi (choijm@dku. edu) #include <stdio. h> #include <stdlib. h> // thread example // by J. Choi (choijm@dku. edu) #include <stdio. h> #include <stdlib. h> int a = 10; void *func() { a++; printf("pid = %dn", getpid()); } int main() { int pid; int main() { int p_thread; } if ((pid = fork()) == 0) { //need exception handle func(); exit(0); } wait(); printf("a = %d by pid = %dn", a, getpid()); if ((pthread_create(&p_thread, NULL, func, (void *)NULL)) < 0) { exit(0); } pthread_join(p_thread, (void *)NULL); printf("a = %d by pid = %dn", a, getpid()); }

Issues on multitask (6/6) Thread: compile and execution

Summary Understand how to create a task Understand how to execute a new program Grasp the role and internals of shell Discuss issues on multitask ü ü IPC (Inter Process Communication) Race condition Virtual memory Differences between task and thread Homework 5: Make a shell Requirements - implement basic logic (parsing, fork(), execve()) - implement background processing - shows student’s ID and date (using whoami and date) - hand out a report that includes a snapshot (21 page) and discussion - send the report, source code and binary to TA Bonus: implement redirection 30

Appendix 1 How to download files from Linux server? ü scp (secure copy protocol) § A means of securely transferring computer files between a local host and a remote host or between two remote hosts 31

Appendix 1 How to download files from Linux server? ü ftp (File Transfer Protocol) § a standard network protocol used for the transfer of computer files between a client and server on a computer network ü sftp (secure ftp) 32

Appendix 1 How to download files from Linux server? ü Using free ftp application with GUI 33

Appendix 2 Revisit “gdb” 34

Appendix 2 Revisit “gdb” 35
- Slides: 35