[email protected] Article directory process/thread related 3 execXX function group execXX 4 execve execve 20 sleep sleep 67 wait function group wait 86 wai...">

当前位置:网站首页>Process/Thread Related in Sandbox - 2

Process/Thread Related in Sandbox - 2

2022-08-09 13:54:00 to raise pigs

[email protected]

进程/线程相关

execXX 函数组

exec函数族提供了一个在进程中启动另一个程序执行的方法.它可以根据指定的文件名或目录名找到可执行文件,
并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新的进程替换了.
另外,这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行的脚本文件.

exec函数一共有六个,其中execveFor kernel-level system calls,
其他(execl,execle,execlp,execv,execvp)都是调用execve的库函数.
The difference is in how the program is found、How to specify the parameters and where the environment comes from.

  • 名称中带有 v 的调用,Specified with an array parameterargv[]An array of new programs.数组的最后一个元素为 NULL.

  • 名称中带有 l 的调用,Take the arguments of the new program as a variable-length argument list of the function itself.The parameter ends with the parameter pointer(char *)NULL.
    You should always do type conversions,因为NULLis actually an integer constant,And the default argument conversion when calling a variadic function doesn't convert it to a pointer.

  • 名称中带有 e 的调用,需要一个额外的参数(或lparameters in the case)to provide an environment for new programs;否则,The program will inherit the environment of the current process.

execve

  • 头文件:
#include<unistd.h>
  • 函数说明:
    pthread_create是类Unix操作系统(Unix、Linux、Mac OS X等)的创建线程的函数.
    它的功能是创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后,就开始运行相关的线程函数.

  • 函数定义:

int execve(const char *pathname, char *const argv[], char *const envp[]);
  • 返回值:
    如果执行成功则函数不会返回(The following code will not be executed),执行失败则直接返回-1,失败原因存于errno 中.

  • 示例代码:

/** * @Author: 吉松阳 * @Date: 2021/9/22 * @Description: */
#include<unistd.h>

int main() {
    
    char *argv[] = {
    "ls", "-el", NULL};
    char *envp[] = {
    "PATH=/bin", 0};
    execve("/bin/ls", argv, envp);
}
/* total 128 drwxr-xr-x 5 jisongyang staff 160 Sep 22 22:07 CMakeFiles -rw-r--r-- 1 jisongyang staff 6687 Sep 22 22:06 Makefile -rw-r--r-- 1 jisongyang staff 1021 Sep 22 22:06 cmake_install.cmake -rwxr-xr-x 1 jisongyang staff 50424 Sep 22 22:22 test_execve */

参考链接:

  1. execve(2) — Linux manual page
  2. What is the difference between the functions of the exec family of system calls like exec and execve?

sleep

  • 头文件:
#include <unistd.h>
  • 函数说明:
    sleep()会令目前的进程暂停, 直到达到参数seconds 所指定的时间, 或是被信号所中断.

  • 函数定义

unsigned int sleep(unsigned int seconds);
  • 返回值
    If the process is paused to the parameterseconds The specified time is returned0, 若有信号中断则返回剩余秒数.

wait 函数组

进程调用 exit() After exit execution,is set to a zombie state.
At this point the parent process can pass wait4() 系统调用查询子进程是否终结,Then do the final operation,Completely delete the memory resources occupied by the process.
wait4() 系统调用由 linux 内核实现.
linux The system usually provides wait()、waitpid()、wait3()、wait4() 这四个函数,
The parameters of the four functions are different,There are also subtle differences in semantics,But both return status information about the terminated process.

wait

  • 头文件:
#include <sys/types.h> // 提供类型 pid_t 的定义
#include <sys/wait.h>
  • 函数说明:
    当进程调用 wait() 时,The execution of the current process will be suspended(即阻塞),由 wait() To automatically analyze whether a child process of the current process has exited,
    If such a child process that has become a zombie process is found,wait 就会收集这个子进程的信息,And return it after destroying it completely;
    如果没有找到这样一个子进程,wait 就会一直阻塞在这里,直到出现僵尸进程.

  • 函数定义

pid_t wait(int *status);

参数 status 保存着子进程退出时的一些状态(包括 task_struct、thread_infoand kernel stack, etc)它是一个指向 int 类型的指针;
If you don't care about the end state value of the child process,只想把这个僵尸进程消灭掉(实际上,This is done most of the time),You can set this parameter to NULL.

关于 status参数比较复杂,可以参考这里
传送门

  • 返回值
    如果 wait() 调用成功,will return the process of the collected child processID;If the called process has no child processes,则调用失败,返回 -1

waitpid

  • 函数原型:
pid_t waitpid(pid_t pid,int *status,int options);

waitpid() 函数的功能与 wait() 的功能类似,不过,它比 wait() 函数多了两个参数:

  • 1)参数 pid It is the identification code of the child process to wait:
    pid < -1 :等待进程组 ID 为 pid The absolute value of any child process in the process group;
    pid = -1 :等待任何子进程,此时 waitpid() 相当于 wait().实际上,wait()就是 pid = -1、options = 0 的waitpid(), 且有:
    pid = 0 :等待进程组 ID Any child processes that are the same as the current process(That is, waiting for any child process in the same process group);
    pid > 0 :等待任何子进程 ID 为 pid 的子进程,只要指定的子进程还没有结束,waitpid() 就会一直等下去.

  • 2)参数 options 提供一些额外的选项来控制 waitpid():
    WNOHANG:If there are no child processes that have ended,则马上返回,不等待;
    WUNTRACED:If the child process enters a situation where execution is suspended,则马上返回,但结束状态不予理会;
    It is also possible to combine these two options,使用 OR 操作.If you don't want to use these two options,也可以直接把 options 设为 0

  • 3)waitpid() 的返回值,有三种:
    a)正常返回时,waitpid() 返回收集到的子进程的PID;
    b)如果设置了 WNOHANG,而调用 waitpid() 时,No exited child processes were found to collect,则返回0;
    c)如果调用出错,则返回 -1,这时erron 会被设置为相应的值以指示错误所在.(当 pid The indicated subprocess is fine,或此进程存在,但不是调用进程的子进程, waitpid() 就会返回出错,这时 erron 被设置为 ECHILD)

wait3/wait4

函数原型

#include <sys/tpyes.h>
#include <sys/wait.h>

pid_t wait3(int *status,int options,struct rusage *rusage);
pid_t wait4(pid_t pid,int *status,int options,struct rusage *rusage);

wait3() 和 wait4() In addition to the function to obtain the status information of the child process,Resource usage information for child processes can also be obtained,This information is passed through parameters rusage 得到的.
而 wait3() 与 wait4() 之间的区别是,wait3() 等待所有进程,而 wait4() 可以根据 pid The value of selects the child process to wait on.
参数 pid 的意义与 waitpid() 函数的一样.

其中,需要注意的是,参数rusageReturns the resource usage of the terminated child process in the structure pointed to.These include those used by the processCPUTotal time and statistics for memory management.
如下,defined for its structure:

struct rusage {
    
    struct timeval ru_utime; /* user CPU time used */
    struct timeval ru_stime; /* system CPU time used */
    long   ru_maxrss;        /* maximum resident set size */
    long   ru_ixrss;         /* integral shared memory size */
    long   ru_idrss;         /* integral unshared data size */
    long   ru_isrss;         /* integral unshared stack size */
    long   ru_minflt;        /* page reclaims (soft page faults) */
    long   ru_majflt;        /* page faults (hard page faults) */
    long   ru_nswap;         /* swaps */
    long   ru_inblock;       /* block input operations */
    long   ru_oublock;       /* block output operations */
    long   ru_msgsnd;        /* IPC messages sent */
    long   ru_msgrcv;        /* IPC messages received */
    long   ru_nsignals;      /* signals received */
    long   ru_nvcsw;         /* voluntary context switches */
    long   ru_nivcsw;        /* involuntary context switches */
};

Three of the more important ones:

  1. timeval ru_utime; /* user CPU time used */ 用户态CPU使用时间
  2. timeval ru_stime; /* system CPU time used */ 内核态CPU使用时间
  3. ru_maxrss; /* maximum resident set size */ Maximum resident set

还可以shell中使用

man getrusage

如何使用int* status

如果参数status的值不是NULL,wait就会把子进程退出时的状态取出并存入其中,This points to an integer value(int),
指出了子进程是正常退出还是被非正常结束的,以及正常结束时的返回值,或被哪一个信号结束的等信息.
Since this information is stored in The distinct bits of an integer中,所以用常规的方法读取会非常麻烦,
So a special set of macros was designed to do this job,Here are some of the most commonly used ones.

请注意,in the macro below status 虽然名字一样,这里的参数status并不同于wait中的参数
One is a pointer to an integer,而是那个指针所指向的整数,切记不要搞混.

WIFEXITED(int status)

This macro is used to indicate whether the process exited normally,如果是,它会返回一个非零值.

WEXITSTATUS(status)

当WIFEXITED返回非零值时,This macro can be used to extract子进程的返回值.
如果子进程调用exit(5)退出,WEXITSTATUS(status) 就会返回5;如果子进程调用exit(7),WEXITSTATUS(status)就会返回7.
请注意,如果进程不是正常退出的,也就是 说,WIFEXITED返回0,这个值就毫无意义.

So the two are often used together in this way:

//Exit judgment normally
if(WIFEXITED(status)){
    
    printf("child exit with %d\n", WEXITSTATUS(status));
}

WIFSIGNALED(status)

This macro is used to indicate if the process exited unexpectedly due to an unhandled signal,如果是,返回非零0.

当 WIFSIGNALED 返回非零值时,此时可通过WTERMSIG(status)get makesThe signal number of the process exit

So the two can be used together in this way

//Because of some kind of signal interrupt getting state
if(WIFSIGNALED(status)){
    
    printf("child killed by %d\n", WTERMSIG(status));
}
原网站

版权声明
本文为[to raise pigs]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/221/202208091244510560.html