Sunday, August 3, 2014

Unix Prog: Unix System Overview - Process

1. Process Basic
Program: an executable file in disk. It will be read into memory and executed by the kernel

Process: an executing instance of a program. And each process has an unique numeric number as id.

outputid.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
   
 int main(void)  
 {  
  printf("Hello this process id is: %d\n", getpid());  
  exit(0);  
 }  

shell:
Run the outputid.out for 2 times, each time the file is read into memory and get executed by kernel, while generating a numeric process id.(10694, 10697)
 ubuntu@ip-172-31-23-227:~$ ./outputid.out  
 Hello this process id is: 10694  
 ubuntu@ip-172-31-23-227:~$ ./outputid.out  
 Hello this process id is: 10697  

Explanation:
getpid is defined at the unistd.h
 ubuntu@ip-172-31-23-227:~$ less /usr/include/unistd.h  
 ......  
   
 /* Get the process ID of the calling process. */  
 extern __pid_t getpid (void) __THROW;  
   
 ......  

2. Quick Introduction of execlp:
myshell.c:
 #include<stdio.h>  
 #include<unistd.h>  
   
 int main(void)  
 {  
  printf("Start to run the script!\n");  
   
  // execlp will start a new process with the same pid of current  
  // process, and that new process will replace current process if  
  // it runs the command successfully, which means, if execlp running  
  // well, the remaining code after execlp will not be executed.  
   
  // And execlp will firstly find the file specified by first argument  
  // under PATH variable. If found, it will run the command specified  
  // by first argument, and take remaining arguments as "argv[0]"  
  // "argv[1]" ... and the last argument must be (char*)0, to indicate  
  // the end of entire commands. Normally first 2 arguments of execlp  
  // should be same.  
  execlp("ls", "ls", "-l", (char*)0);  
  printf("Failed to run the script!\n");  
   
  return 0;  
 }  

shell:
Since execlp successfully replaced the current process with new process, so the last printf statement is not executed at all.
 ubuntu@ip-172-31-23-227:~$ ./myshell.out  
 Start to run the script!  
 total 16  
 -rw-rw-r-- 1 ubuntu ubuntu 831 Aug 3 15:15 myshell.c  
 -rw-rw-r-- 1 ubuntu ubuntu  0 Aug 3 15:05 myshell.c~  
 -rwxrwxr-x 1 ubuntu ubuntu 8565 Aug 3 15:15 myshell.out  

Explanation:
execlp is declared at "unistd.h"
 ubuntu@ip-172-31-23-227:~$ less /usr/include/unistd.h  
   
 ......  
   
 /* Execute FILE, searching in the `PATH' environment variable if  
   it contains no slashes, with all arguments after FILE until a  
   NULL pointer and environment from `environ'. */  
 extern int execlp (const char *__file, const char *__arg, ...)  
    __THROW __nonnull ((1, 2));  
   
 ......  

3. Process Control
myshell.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<string.h>  
 #include<sys/wait.h>  
   
 #define MAXLINE 1000  
   
 void err_ret(const char* msg)  
 {  
  printf("%s\n", msg);  
  exit(127);  
 }  
   
 void err_sys(const char* msg)  
 {  
  printf("%s\n", msg);  
  exit(1);  
 }  
   
 int main(void)  
 {  
  char buf[MAXLINE];  
  pid_t pid;  
  int status;  
   
  printf("%% ");  
  // Keep reading in the command from standard input, until  
  // user put in the Ctrl + D to stop  
  while(fgets(buf, MAXLINE, stdin) != NULL)  
   {  
    if(buf[strlen(buf)-1] == '\n')  
     buf[strlen(buf)-1] = 0; // Replace new line with null  
   
    // fork will make a copy of current process, and return values to  
    // 2 processes: return 0 to child process, and return child process id  
    // to parent process.  
   
    // After calling fork() here, the child process will continue to runx  
    // after this line, but just get the pid (0). So it will call execlp  
    // to start a new process with same pid to replace the child process,  
    // execute the command and exit.  
   
    // Note: we have to use fork() to start a new child process here,  
    // otherwise, the execlp generated new process will replace current  
    // process(include the looping to receive user command) and user has  
    // no opportunity to input command in the next loop.  
    if((pid = fork()) < 0)  
     {  
      err_sys("fork error");  
     }  
     else if(pid == 0)  
      {  
       execlp(buf, buf, (char*)0);  
       err_ret("could not execute the buffered command");  
      }  
   
    // waitpid is matching the process with same pid as first argument  
    // then wait for it to stop, then save the dead process status in 2nd  
    // argument, the 3rd argument is for "option bits", like WNOHANG(if child  
    // process is still running, the waitpid will return 0 immediately).  
     if((pid = waitpid(pid, &status, 0)) < 0)  
      err_sys("waitpid error");  
   
     printf("%% ");  
   }  
   
  exit(0);  
 }  

shell:
 ubuntu@ip-172-31-23-227:~$ ./myshell.out  
 % ls  
 myshell.c myshell.c~ myshell.out  
 % date  
 Sun Aug 3 17:37:59 UTC 2014  

4. Threads
1) All the threads within a process can share the same address space, file descriptors, stacks and process-related attributes.

2) Because they can access same process memory spaces, they need to synchronize themselves to avoid data inconsistencies

3) Threads are identified by IDs, and it is only local to current process.

No comments:

Post a Comment