Posts Linux Task Management
Post
Cancel

Linux Task Management

Process, Thread and Task

Managing unitDescription
TaskResource acquisition unit
ThreadRunning unit
ProcessRunning or runnable program
ProgramExecutable file stored in disk
  • Executable file is compiled to be a set of binary machine instructions and data

  • Program and Process

1
2
3
4
5
6
7
8
9
10
$ gcc -o test test.c
$ file test
test: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=c1919678864f40218323926252afd86ca1cc01dc, with debug_info, not stripped
$ ls test # Program
test
$ ps
  PID TTY          TIME CMD
  814 pts/3    00:00:00 bash
 6507 pts/3    00:00:00 test    # Process
 6508 pts/3    00:00:00 ps
  • Scheduling is determining processes to acquire CPU resource by the Kernel.

Process structure

  • Virtual address space structure
    • One of the representative resource being allocated by the kernel to run process
    CPUVirtual memory allocationUser spaceKernel space
    32bit4 GB 2^(2+10+10+10)0 ~ 3 GB3 ~ 4 GB
    64bit16 EB (Exa = 1024^6)0 ~ 128 TB128 TB ~ 16 EB

    Virtual address space structure

    Segment (Virtual Memory Area Structure)LocationContents
    Stack regionGrowing down from 3GB(32bit) or 128TB(64bit)Local variables and arguments for functions
    Heap regionGrowing up from the top of Data regionDynamically allocated memory with malloc() / new()
    Data regionFixed region on top of Text regionGlobal variables
    Text regionFixed region at the beginning of user spaceCPU instructions

Creation and Execution of Process and Thread

  • fork()

    #include <sys/types.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int global_cnt = 2;
    
    int main(void)
    {
      pid_t pid;
      int local_cnt = 3;
    
      printf("PID(%d): Parent global_cnt=%d, local_cnt=%d \n", getpid(), global_cnt, local_cnt);
    
      if (pid = fork() < 0) {
        perror("fork error");
        exit(1);
      }
      else if (pid == 0) {
        global_cnt++
        local_cnt++
      }
      else {
        wait();
      }
    
      printf("PID(%d): global_cnt=%d, local_cnt=%d \n", getpid(), global_cnt, local_cnt);
    
      return 0;
    }
    
    1
    2
    3
    4
    5
    
    $ gcc -o fork fork.c
    $ ./fork
    PID(10404): Parent global_cnt=2, local_cnt=3
    PID(10405): global_cnt=3, local_cnt=4
    PID(10404): global_cnt=2, local_cnt=3
    
  • clone()

    // #include <sys/types.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sched.h>
    
    int global_cnt = 2;
    
    int sub_func(void *arg)
    {
      global_cnt++;
      printf("PID(%d): Child global_cnt=%d \n", getpid(), global_cnt);
      sleep(2);
      return 0;
    }
    
    
    int main(void)
    {
      pid_t pid;
      int child_stack[4096];
      int local_cnt = 3;
    
      printf("PID(%d): Parent global_cnt=%d, local_cnt=%d \n", getpid(), global_cnt, local_cnt);
    
      clone(sub_func, (void *)(child_stack+4095), CLONE_VM | CLONE_THREAD | CLONE_SIGHAND, NULL);
      sleep(1);
    
      printf("PID(%d): Parent global_cnt=%d, local_cnt=%d \n", getpid(), global_cnt, local_cnt);
    
      return 0;
    }
    
    1
    2
    3
    4
    5
    
    $ gcc -o clone clone.c
    $ ./clone
    PID(17351): Parent global_cnt=2, local_cnt=3
    PID(17351): Child global_cnt=3
    PID(17351): Parent global_cnt=3, local_cnt=3
    
     Forked ProcessCloned Thread
    Virtual memory address spaceCreate anotherShare the same
    Resource costDoubledMinimized
    Error propagationParent is not affectedParent can be affected
  • execl()

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  pid_t pid;
  int exit_status;

  if (pid = fork() < 0) {
    perror("fork error");
    exit(1);
  }
  else if (pid == 0) {
    printf("Before execl() \n");
    execl("./fork", "fork", (char *)0);
    printf("After execl() \n");
  }
  else {
    pid = wait(&exit_status);
  }

  printf("Parent \n");

  return 0;
}
1
2
3
4
5
6
7
$ gcc -o fork_exec fork_exec.c
$ ./fork_exec
Before execl()
PID(17453): Parent global_cnt=2, local_cnt=3
PID(17454): global_cnt=3, local_cnt=4
PID(17453): global_cnt=2, local_cnt=3
Parent
  • After execl() is not printed because “execl()” replace the process image “fork_exec” (including text, data, stack) with the previous image “fork”.
  • In this case, “vfork()” can be used for the same address space with parent’s so that redundant memory space does not created before being replaced with the previous image “fork”.

Linux task model

This post is licensed under CC BY 4.0 by the author.