C language - process management

Basic concepts of process

A process is an execution process of a program with certain functions about a data set. The Linux system supports multiple processes at the same time. A priority is set in the security information in each process attribute. The system determines the size of the time slice obtained by each process from the CPU according to the priority.

The Linux kernel turns processes into task s. The virtual address space of processes is divided into user virtual address space and kernel virtual address space. All processes share the kernel virtual address space, and each process has an independent user virtual address space.

Processes have two special forms: processes without user virtual address space become kernel threads, and processes sharing user virtual address space become user threads. User threads are usually referred to as threads without confusion. All threads sharing the same user virtual address space form a thread group.

The corresponding relationship between process terms of C standard library and Linux kernel is as follows:

Process terminology of C standard libraryProcess terminology of the corresponding Linux kernel
A process that contains multiple threadsThread group
A process with only one threadProcess or task
thread Processes that share user virtual address space

Properties of the process

Each process has its own attributes, which are briefly introduced below:

attributeeffect
Process identifier (PID)The identifier assigned to it by the system
Memory area occupied by the processThe area of memory allocated for the process
Descriptor of related fileFile descriptors in process operation, including standard input, standard output and standard error output
security informationIncluding user ID and group ID, which are used by the kernel to determine the process permissions
process environmentEnvironment variable, command line of program call
signal processing Communication between processes can be carried out through signals
Resource arrangementProcess is the basic unit of scheduling system resources. Different processes use system resources in turn
Synchronous processingThe synchronization between multiple programs is completed by the process, using shared memory, file locking and other methods
Process statusRunning, waiting to be scheduled, sleep status.

Process control correlation function

Process creation

1. Derived process

#include <unistd.h>
pid_t fork(void);
pid_t vfork(void);

When fork is called, the system will create a new process that is the same as the current process. Usually, the original process becomes the parent process and the newly generated process becomes the child process.

Test procedure 1:

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main(void)
{
    pid_t pid;
    printf("hello nfk!     !\n");
    printf("hello ubuntu !\n");
    printf("hello !");
    if((pid=fork())<0){
        printf("fork error!\n");
        exit(1);
    }else if(pid==0){
        printf("Child process is printing\n");
    }else{
        printf("Parent process is printing\n");
    }   
    exit(0);
}

The fork function returns twice, returning the child process PID from the parent process and 0 from the child process. In this method, the parent process has nothing to do with the child process.

hello nfk! !
hello ubuntu !
hello !Parent process is printing
hello !Child process is printing

The test results are as follows: hello! Printed twice. It should be the fork process that copies the data in the buffer at the same time, resulting in hello twice!

At the same time, the program executed by the fork process obviously continues to execute from fork rather than from scratch.

Another way to create a process is vfork, which will wait for the child process to finish before executing the parent process. This method is usually used with exec,

The functions in the exec function family are used to execute new programs and completely replace the original processes with new sub processes. Therefore, generally, after using vfork, use the exec function to directly create a child process.

And__ The clone function is used to create processes. This function has more control over the shared resources of parent-child processes.

Process waiting

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define FORK \
    if((pid=fork())<0){ \
        printf("fork error!\n"); \
        exit(0); \
    } \
    else if(pid==0)

#define WAIT \
    if(wait(&status)!=pid){ \
        printf("wait error!\n"); \
    exit(0); \
    }
void h_exit(int status);

int main(void)
{
    pid_t pid;
    int status;
    FORK exit(7);WAIT//When the child process ends, it returns 7, and the parent process waits for the result to be returned
    h_exit(status);

    FORK exit(1);WAIT//When the child process ends, it returns 1, and the parent process waits for the result to be returned
    h_exit(status);
    
    FORK printf("hello\n");WAIT 
        /*Child process returns result 0,
        At the same time, the child process will also wait, but the returned results cannot be obtained
        The parent process gets the returned result 0*/
    h_exit(status);
    exit(0);
}

void h_exit(int status)
{
    if(WIFEXITED(status))
        printf("normal termination,exit status=%d .\n",WEXITSTATUS(status));
    else if (WIFSIGNALED(status))
        printf("abnormal termination,exit status=%d .\n",WEXITSTATUS(status));
}

The execution result is as follows. After waiting, the parent process will be suspended until the child process ends. wait is dedicated to waiting for child processes. If there are no child processes, an error is returned.

normal termination,exit status=7 .
normal termination,exit status=1 .
hello
wait error!
normal termination,exit status=0 .

End of process

There are several ways to end the process:

#include <stdlib.h>
void exit(int status);//Terminating a running program
int atexit(void(*function)(void));//Register a function with no parameters and return value to be called on exit
int on_exit(void(*function)(int,void*),void *arg);//Register functions with parameters and return values for calling
void abort(void);//Interrupt the function and send a SIGABRT signal to terminate the current process
#include <unistd.h>
void _exit(int status);//Close some Linux specific exit handles
#include <assert.h>
void assert(int expression);

Relationship between multiple processes

Process group

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

pid_t getpgrp(void);
pid_t setpgid(pid_t pid,pid_t pgid);

Through the above functions, you can obtain the process group number and create a process group or add it to a process group.

Time slice allocation

Scheduling strategy and parameters

The kernel supports the following scheduling strategies:

  1. Deadline processes use deadline scheduling policy (SCHED_DEADLINE).
  2. Real time processes support two scheduling strategies: SCHED_FIFO and shched_rr.
  3. Ordinary processes support two scheduling strategies: scheduled_normal and scheduled_idle.
  • The deadline scheduling policy has three parameters: runtime, deadline and period. It runs once in each cycle and is completed before the deadline. The length of one run is runtime.

  • FIFO scheduling has no time slice and is very overbearing. If there is no real-time process with higher priority and it does not sleep, it will always occupy the processor.

  • There is no time slice for round robin scheduling. After the process runs out of time slices, it will be added to the tail of the run queue corresponding to the priority and give the processor to other real-time processes with the same priority.

  • The standard rotation time-sharing strategy uses a completely fair scheduling algorithm to fairly allocate processor time to each process.

  • Idle scheduling strategy is used to execute background jobs with very low priority. The priority is lower than that of ordinary processes using standard rotation time-sharing strategy and relative priority of 19. The relative priority of processes has no impact on idle scheduling strategy.

The priority of deadline process is higher than that of real-time process, and the priority of real-time process is higher than that of ordinary process.

The priority of the deadline process is - 1.

The priority of real-time process is 1 ~ 99, and the priority value is.

The static priority of ordinary processes is 100139. The smaller the priority level, the higher the priority. The priority of ordinary processes can be changed by modifying the nice value (i.e. relative priority, the value range is - 2019). The priority is equal to 120 plus the nice value.

Scheduling class:

Scheduling classscheduling strategy scheduling algorithm Scheduling object
Shutdown scheduling classnothingnothingShutdown process
Deadline scheduling classSCHED_DEADLINEEarliest deadline firstDeadline process
Real time schedulingSCHED_FIFO,SCHED_RRFirst in, first out, scheduling in turnReal time process
Fair schedulingSCHED_NORMAL,SCHED_IDLEFully fair scheduling algorithmOrdinary process
idle schedule nothingnothingIdle processes per processor

When scheduling, the kernel will select from the running queue and schedule according to the priority of the scheduling class. The priority from high to low is shutdown, deadline, real-time, fair and idle respectively. That is, select processes from deadline queue, real-time queue and fair queue for scheduling.

Priority Setting

#include <unistd.h>
int nice(int inc);//Change the dynamic priority of the process

#include <sys/time.h>
#include <sys/resource.h>
int setpriority(int which,int who,int prio);//set priority
int getpriority(int which,int who);//Get priority

#include <sched.h>
int sched_set_priority_max(int policy);//Set to the highest priority of the specified policy
int sched_set_priority_min(int policy);//Set to the lowest priority of the specified policy

Process synchronization

File locking, semaphore, semaphore, pipeline and socket can complete inter process synchronization and prevent multiple processes from grabbing the same resources.

thread

The same process can be divided into several threads. The biggest feature of threads in Linux system is that the call of threads is realized by the system kernel scheduler. Each thread has its own process number. Threads consume less system resources and communicate with each other easily.

Thread creation

#include<pthread.h>
int pthread_create(pthread_t* thread,pthread_attr *attr,void *(*start_rouline) (void*),void *arg)

Where start_rouline refers to the function pointer of the program called by this thread.

Thread property settings will not be analyzed temporarily.

Thread end, suspend, cancel

Thread end:

#include <pthread.h>
void pthread_exit(void *retval);

Thread pending:

#include <pthread.h>
int pthread_join(pthread_t th,void **thread_return);

Suspend the current thread until the specified thread terminates. th is the thread to wait for termination. thread_return is used to store the return value of other threads. For specific usage, consider subsequent routines.

The user can suspend a thread until a condition is met

#include <pthread.h>
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);//Initialize an object
int pthread_cond_destroy(pthread_cond_t *cond);//Detects whether a thread is waiting for the specified thread
int pthread_cond_signal(pthread_cond_t *cond);//Used to restart a suspended thread
int pthread_cond_broadcast(pthread_cond_t *cond);//Restart all pending processes
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);//Wait for mutex thread
int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex,const struct timespec *abstime);//You can specify the time to wait for the mutex thread

Thread cancellation:

#include <pthread.h>
int pthread_cancel(pthread_t thread);//Cancel thread
int pthread_setcancelstate(int state,int * oldstate);//Set the thread's own state
int pthread_setcanceltype(int type,int * oldstate);//Set the corresponding method of cancellation, including immediate cancellation and cancellation at the cancellation point
int pthread_testcancel(void);//Set cancellation point

type:

PTHREAD_CANCLE_ASYNCHRONOUS cancel now

PTHREAD_ CANCLE_ Delayed cancellation to cancellation point

mutex

Mutex lock: the user locks the resource. At the same time, only one thread can lock it. When another thread tries to unlock it, it will be suspended until the mutex is unlocked.

Mutually exclusive functions include:

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *mutexattr);//Construct mutual exclusion
int pthread_mutex_destroy(pthread_mutex_t *mutex);//Cancel a mutex
int pthread_mutex_lock(pthread_mutex_t *mutex);//Mutually exclusive locking
int pthread_mutex_trylock(pthread_mutex_t *mutex);//Thread is suspended only when mutex is locked
int pthread_mutex_unlock(pthread_mutex_t *mutex);//Unlock a mutex

Tags: C Linux Embedded system Operating System

Posted by nevillejones on Tue, 26 Apr 2022 14:58:10 +0300