160 likes | 306 Vues
This discussion focuses on fundamental process management concepts in C programming, including process creation using `fork`, executing new programs with `exec`, and managing process lifecycle through `wait` and `kill`. We will review coding practices and their importance in ensuring safer and more robust code. Key topics include definitions and differences between programs and processes, effective use of system calls, as well as handling common pitfalls during process management. Join us for an engaging open discussion to clarify these essential topics!
E N D
CS241 Systems Programming Discussion Section Week 2 Nat Thompson
Agenda • Mp0 quiz • Review mp0 • Fork,exec,etc. • Open discussion time
Outline • fork • exec • Wait • kill • Coding practices
Program vs Process • Program • .h/.c -> .o -> executable • Plan to complete a task • Process • Instance of a program (ie currently executing) • Has alterable state, variables, memory
Process Creation • Running a process from the shell • ls • uptime • Double clicking an icon • Creating a new process in C • fork()
fork • To create a new process within C: • pid_t fork() • http://www.penguin-soft.com/penguin/man/2/fork.html • A new process is created • exactly the same as parent process • except process id and parent id
fork example #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char** argv) { pid_t child_pid = -1; child_pid = fork(); if (child_pid < 0) { printf(”it’s an error!!\n”); } else if (child_pid == 0) { printf(”I’m the child process!!\n”); } else { printf(”child process %d created\n”, child_pid); } return 0; }
exec • fork() creates a new process, but it is still running same program • to load a new program into a process we use exec() • int execve(const char * filename , char *const argv [], char *const envp []); • existing process is overwritten with specified binary • http://www.penguin-soft.com:80/penguin/man/2/execve.html
exec variations • execl, execlp, execle, execv, execvp, execve • “l” : list of arguments • “v” : vector of arguments (think array) • “p” : file pointer to binary • “e” : environment specified
exec example #include <unistd.h> int main(int argc, char** argv) { char *progname = get_prog_name(argc, argv); char **progargs = get_prog_args(argc, argv); ... child_pid = fork(); if (child_pid < 0) { printf(“it’s an error!!\n”); } else if (child_pid == 0) { if (execv(progname, progargs) < 0) { printf(”failed to execute %s!\n”, progname); perror(”child exec:”); return -1; } } ... return 0; }
wait • parent process needs to wait for child process to finish • can wait for a specific process to finish using waitpid() function • pid_t waitpid(pid_t pid , int * status , int options); • blocks until pid is done executing • copies specified process’s return value into status • http://www.penguin-soft.com/penguin/man/2/wait.html
wait example #include <sys/types.h> #include <sys/wait.h> int main(int argc, char** argv) { int result = 0; ... child_pid = fork(); if (child_pid == 0) { printf(”I’m the child process!!\n”); return 100; } else { if (waitpid(child_pid, &result, 0) == -1) { perror(”wait failed:”); return -1; } printf(”child %d returned %d\n”, child_pid, result); } return 0; }
wait gotcha • parent process might receive signals that interrupt wait • causes wait to return even though child not finished! • need to check wait return value: while((waitpid(childpid, NULL, 0) == -1) && (errno = EINTR))
Killing Children (Processes) • A child process can be terminated using the kill command • Really kill just sends a signal to the process • int kill(pid_t pid , int sig ); if (kill(child_pid, SIGTERM) == 0) { /* successfully sent signal */ } • More on signal handling later
Coding practice • C-compiler will let you get away with a lot • heed warnings - leads to safer code • are casts valid? Is that what you meant? - if so do it explicitly! • Make sure to include necessary .h files • Always set default values for variables • Always check return values from functions
Debugging • printf is great, but it’s a pain to remove all printfs when debugging done • use the preprocessor! #ifdef DEBUG printf(”My Debug Statement\n”); #endif • enable with gcc -DDEBUG • block comments: #if 0 ... #endif