Linux进程管理Part2

news2024/11/15 17:32:29

Linux进程控制Part2

文章目录

  • Linux进程控制Part2
    • Fork()函数详解
      • 简单描述
    • fork函数的使用
    • 进程退出的方式
      • _exit函数
      • exit函数
      • return 退出
    • 进程等待
      • 进程等待的方法
    • kill的使用
    • 进程替换
      • 简单描述
        • 命名原理
  • END

Fork()函数详解

FORK(2) Linux Programmer’s Manual FORK(2)

NAME
fork - create a child process

SYNOPSIS
#include <unistd.h>

   pid_t fork(void);

DESCRIPTION
fork() creates a new process by duplicating the calling process. The new process, referred to as the child, is an exact duplicate of the calling
process, referred to as the parent, except for the following points:

   *  The child has its own unique process ID, and this PID does not match the ID of any existing process group (setpgid(2)).

   *  The child's parent process ID is the same as the parent's process ID.

   *  The child does not inherit its parent's memory locks (mlock(2), mlockall(2)).

   *  Process resource utilizations (getrusage(2)) and CPU time counters (times(2)) are reset to zero in the child.

   *  The child's set of pending signals is initially empty (sigpending(2)).

   *  The child does not inherit semaphore adjustments from its parent (semop(2)).

   *  The child does not inherit record locks from its parent (fcntl(2)).

   *  The child does not inherit timers from its parent (setitimer(2), alarm(2), timer_create(2)).

   *  The child does not inherit outstanding asynchronous I/O operations from its parent (aio_read(3), aio_write(3)), nor does it inherit any asynchro‐
      nous I/O contexts from its parent (see io_setup(2)).

   The  process  attributes  in  the  preceding list are all specified in POSIX.1-2001.  The parent and child also differ with respect to the following
   Linux-specific process attributes:

   *  The child does not inherit directory change notifications (dnotify) from its parent (see the description of F_NOTIFY in fcntl(2)).

   *  The prctl(2) PR_SET_PDEATHSIG setting is reset so that the child does not receive a signal when its parent terminates.

   *  The default timer slack value is set to the parent's current timer slack value.  See the description of PR_SET_TIMERSLACK in prctl(2).

   *  Memory mappings that have been marked with the madvise(2) MADV_DONTFORK flag are not inherited across a fork().

   *  The termination signal of the child is always SIGCHLD (see clone(2)).

   *  The port access permission bits set by ioperm(2) are not inherited by the child; the child must turn on any bits  that  it  requires  using  iop‐
      erm(2).

   Note the following further points:

   *  The  child  process  is created with a single thread—the one that called fork().  The entire virtual address space of the parent is replicated in
      the child, including the states of mutexes, condition variables, and other pthreads objects; the use of  pthread_atfork(3)  may  be  helpful  for
      dealing with problems that this can cause.

   *  The  child inherits copies of the parent's set of open file descriptors.  Each file descriptor in the child refers to the same open file descrip‐
      tion (see open(2)) as the corresponding file descriptor in the parent.  This means that the two descriptors share open file status flags, current
      file offset, and signal-driven I/O attributes (see the description of F_SETOWN and F_SETSIG in fcntl(2)).

   *  The child inherits copies of the parent's set of open message queue descriptors (see mq_overview(7)).  Each descriptor in the child refers to the
      same open message queue description as the corresponding descriptor in the parent.  This means that the two  descriptors  share  the  same  flags
      (mq_flags).

   *  The  child  inherits  copies  of the parent's set of open directory streams (see opendir(3)).  POSIX.1-2001 says that the corresponding directory
      streams in the parent and child may share the directory stream positioning; on Linux/glibc they do not.

RETURN VALUE
On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no
child process is created, and errno is set appropriately.

ERRORS
EAGAIN fork() cannot allocate sufficient memory to copy the parent’s page tables and allocate a task structure for the child.

   EAGAIN It  was  not  possible  to  create a new process because the caller's RLIMIT_NPROC resource limit was encountered.  To exceed this limit, the
          process must have either the CAP_SYS_ADMIN or the CAP_SYS_RESOURCE capability.

   ENOMEM fork() failed to allocate the necessary kernel structures because memory is tight.

   ENOSYS fork() is not supported on this platform (for example, hardware without a Memory-Management Unit).

CONFORMING TO
SVr4, 4.3BSD, POSIX.1-2001.

NOTES
Under Linux, fork() is implemented using copy-on-write pages, so the only penalty that it incurs is the time and memory required to duplicate the
parent’s page tables, and to create a unique task structure for the child.

   Since  version  2.3.3, rather than invoking the kernel's fork() system call, the glibc fork() wrapper that is provided as part of the NPTL threading
   implementation invokes clone(2) with flags that provide the same effect as the traditional system call.  (A call to fork() is equivalent to  a  call
   to clone(2) specifying flags as just SIGCHLD.)  The glibc wrapper invokes any fork handlers that have been established using pthread_atfork(3).

EXAMPLE
See pipe(2) and wait(2).

SEE ALSO
clone(2), execve(2), exit(2), setrlimit(2), unshare(2), vfork(2), wait(2), daemon(3), capabilities(7), credentials(7)

COLOPHON
This page is part of release 3.53 of the Linux man-pages project. A description of the project, and information about reporting bugs, can be found
at http://www.kernel.org/doc/man-pages/.

Linux 2013-03-12 FORK(2)

以上为LinuxMan2号手册里的fork函数详解

简单描述

简单来讲就是使用fork()创建一个子进程,主进程返回子进程的pid,子进程返回的pid值为0。

fork函数的使用

1、 fork生成的子进程和父进程共享代码,他们的数据也是共享的,但是当一方发生写入时,就会通过写时拷贝来保证数据的安全性。

2、 子进程需要父进程等待,不然会导致僵尸进程发生内存泄漏。

eg:

#include <iostream>
#include<unistd.h>

using namespace std;

int main()
{
  pid_t pid=fork();
  if(pid==0)
  {
      cout<<"I am a Child Process"<<"pid:"<<getpid()<<"ppid:"<<getppid()<<endl;
      cout<<endl;
  }
  else
  {
    while(1)
    {
      cout<<"i am a Parent Process"<<"pid:"<<getpid()<<"ppid:"<<getppid()<<endl;
      cout<<endl;
      sleep(1);
    } 
  }
  return 0;
}

在这里插入图片描述

观察可得子进程的STAT为Z+了,也就是变成了僵尸进程,这样就会造成内存泄漏

进程退出的方式

进程常见退出方式有三种

正常退出:

  1. 从mian返回

  2. 调用exit

  3. _exit

异常退出:

​ ctrl+c

_exit函数

void _exit(int status);

参数:status 定义了进程的终止状态,父进程通过wait来获取该值

说明:虽然status是int,但是仅有低8位可以被父进程所用。所以_exit(-1)时,在终端执行$?发现返回值是255。

exit函数

void exit(int status);

exit最后也会调用exit, 但在调用exit之前,还做了其他工作:

  1. 执行用户通过 atexit或on_exit定义的清理函数。
  2. 关闭所有打开的流,所有的缓存数据均被写入
  3. 调用_exit

return 退出

return是一种更常见的退出进程方法。执行return n等同于执行exit(n),因为调用main的运行时函数会将main的返回值当做 exit的参数。

进程等待

之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。
另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法
杀死一个已经死去的进程。
最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,
或者是否正常退出。
父进程通过进程等待的方式,回收子进程资源,获取进程退出信息

进程等待的方法

等待进程的函数有两个分别是wait()和waitpid()。

pid_t wait(int*status);
//status 是输出型参数,用来获取进程退出状态若不关心则可以设置为null
//返回值:
//成功返回被等待进程pid,失败返回-1
pid_ t waitpid(pid_t pid, int *status, int options);
/*
返回值:
当正常返回的时候waitpid返回收集到的子进程的进程ID;
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
pid:
Pid=-1,等待任一个子进程。与wait等效。
Pid>0.等待其进程ID与pid相等的子进程。
status:
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
options:
WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进
程的ID。
*/

kill的使用

在这里插入图片描述

现在我们学习kill -9 信号

作用就是杀掉指定pid的进程(对僵尸进程无效)

拿上个程序举例,父进程一直在循环执行,在右侧终端发出杀进程信号后终止了程序执行。

在这里插入图片描述

进程替换

继续查手册

EXEC(3) Linux Programmer’s Manual EXEC(3)

NAME
execl, execlp, execle, execv, execvp, execvpe - execute a file

SYNOPSIS
#include <unistd.h>

   extern char **environ;

   int execl(const char *path, const char *arg, ...);
   int execlp(const char *file, const char *arg, ...);
   int execle(const char *path, const char *arg,
              ..., char * const envp[]);
   int execv(const char *path, char *const argv[]);
   int execvp(const char *file, char *const argv[]);
   int execvpe(const char *file, char *const argv[],
               char *const envp[]);

Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

   execvpe(): _GNU_SOURCE

DESCRIPTION
The exec() family of functions replaces the current process image with a
new process image. The functions described in this manual page are front-
ends for execve(2). (See the manual page for execve(2) for further details
about the replacement of the current process image.)

   The initial argument for these functions is the name of a file that  is  to
   be executed.

   The  const  char *arg and subsequent ellipses in the execl(), execlp(), and
   execle() functions can be thought of as arg0, arg1,  ...,  argn.   Together
   they  describe  a  list  of one or more pointers to null-terminated strings
   that represent the argument list available to the  executed  program.   The
   first argument, by convention, should point to the filename associated with
   the file being executed.  The list of arguments must  be  terminated  by  a
   NULL pointer, and, since these are variadic functions, this pointer must be
   cast (char *) NULL.

   The execv(), execvp(), and execvpe() functions provide an array of pointers
   to  null-terminated  strings  that represent the argument list available to
   the new program.  The first argument, by convention, should  point  to  the
   filename  associated  with  the file being executed.  The array of pointers
   must be terminated by a NULL pointer.

   The execle() and execvpe() functions allow the caller to specify the  envi‐
   ronment  of  the executed program via the argument envp.  The envp argument
   is an array of pointers to null-terminated strings and must  be  terminated
   by  a  NULL  pointer.  The other functions take the environment for the new
   process image from the external variable environ in the calling process.

Special semantics for execlp() and execvp()
The execlp(), execvp(), and execvpe() functions duplicate the actions of
the shell in searching for an executable file if the specified filename
does not contain a slash (/) character. The file is sought in the colon-
separated list of directory pathnames specified in the PATH environment
variable. If this variable isn’t defined, the path list defaults to the
current directory followed by the list of directories returned by conf‐
str(_CS_PATH). (This confstr(3) call typically returns the value
“/bin:/usr/bin”.)

   If the specified filename includes a slash character, then PATH is ignored,
   and the file at the specified pathname is executed.

   In addition, certain errors are treated specially.

   If permission is denied for a file (the attempted execve(2) failed with the
   error  EACCES),  these  functions  will  continue searching the rest of the
   search path.  If no other file is found, however,  they  will  return  with
   errno set to EACCES.

   If  the  header  of a file isn't recognized (the attempted execve(2) failed
   with the error ENOEXEC), these functions will execute the  shell  (/bin/sh)
   with  the  path of the file as its first argument.  (If this attempt fails,
   no further searching is done.)

RETURN VALUE
The exec() functions return only if an error has occurred. The return
value is -1, and errno is set to indicate the error.

ERRORS
All of these functions may fail and set errno for any of the errors speci‐
fied for execve(2).

VERSIONS
The execvpe() function first appeared in glibc 2.11.

CONFORMING TO
POSIX.1-2001, POSIX.1-2008.

   The execvpe() function is a GNU extension.

NOTES
On some other systems, the default path (used when the environment does not
contain the variable PATH) has the current working directory listed after
/bin and /usr/bin, as an anti-Trojan-horse measure. Linux uses here the
traditional “current directory first” default path.

   The behavior of execlp() and execvp() when errors occur while attempting to
   execute the file is historic practice, but has not traditionally been docu‐
   mented and is not specified by the POSIX standard.  BSD (and possibly other
   systems) do an automatic sleep and retry if ETXTBSY is encountered.   Linux
   treats it as a hard error and returns immediately.

   Traditionally,  the  functions  execlp()  and  execvp()  ignored all errors
   except for the ones described above and ENOMEM and E2BIG, upon  which  they
   returned.  They now return if any error other than the ones described above
   occurs.

SEE ALSO
sh(1), execve(2), fork(2), ptrace(2), fexecve(3), environ(7)

COLOPHON
This page is part of release 3.53 of the Linux man-pages project. A
description of the project, and information about reporting bugs, can be
found at http://www.kernel.org/doc/man-pages/.

GNU 2010-09-25 EXEC(3)

简单描述

#include <unistd.h>`
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
//其实有六种exec族的函数,统称为exec函数
//这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。
//如果调用出错则返回-1
//所以exec函数只有出错的返回值而没有成功的返回值。
命名原理
  • (list) : 表示参数采用列表
  • v(vector) : 参数用数组
  • p(path) : 有p自动搜索环境变量PATH
  • e(env) : 表示自己维护环境变量

进程替换举例

#include <iostream>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

using namespace std;

int main()
{
  pid_t pid=fork();
  if(pid)
  {
    waitpid(pid,NULL,WNOHANG);
  }
  else
  {
    execl("/bin/ls","ls","-la",NULL);
  }
  return 0;
}

在这里插入图片描述

这样就完成了ls的替换

END

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1911113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机的核心工作机制

前言 本篇不介绍代码&#xff0c;主要是理解计算机的一些核心工作机制。想了解更多请跳转-->【【计算机科学速成课】[40集全/精校] - Crash Course Computer Science】 冯诺依曼体系结构 由计算机之父之一冯诺依曼提出的计算机内部构造的基本组成&#xff0c;而现在大多数…

前端使用Vue和Element实现可拖动弹框效果,且不影响底层元素操作(可拖拽的视频实时播放弹框,底层元素可以正常操作)

简述&#xff1a;在前端开发中&#xff0c;弹框和实时视频播放是常见的需求。这里来简单记录一下&#xff0c;如何使用Vue.js和Element UI实现一个可拖动的弹框&#xff0c;并在其中播放实时视频。同时&#xff0c;确保在拖拽弹框时&#xff0c;底层元素仍然可以操作。 一、项目…

用python生成词频云图(python实例二十一)

目录 1.认识Python 2.环境与工具 2.1 python环境 2.2 Visual Studio Code编译 3.词频云图 3.1 代码构思 3.2 代码实例 3.3 运行结果 4.总结 1.认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&a…

B站启用adblock插件导致无法看到评论

1 进入adblock插件的设置页面 2 进入自定义规则页面&#xff0c;编辑过滤规则 删除掉这一项 www.bilibili.com##P 然后&#xff0c;点击保存&#xff1b; 刷新页面就可以看到B站评论区的评论了。

可以拖拽的富文本编辑器(VueDragResize,quill-editor)

该功能实现一个帮助文档的展示和编辑功能&#xff0c;默认进去只能查看帮助文档的内容&#xff0c;点击编辑可以进行富文本编辑器的编辑功能。 出现的问题1.如何隐藏富文本编辑的工具栏并且禁止编辑 //隐藏工具栏this.toolbar this.$refs.myTextEditor.quill.getModule(toolb…

化妆品3D虚拟三维数字化营销展示更加生动、真实、高效!

随着人们越来越追求高速便捷的生活工作方式&#xff0c;企业在营销市场也偏国际化&#xff0c;借助VR全景制作技术&#xff0c;将企业1:1复刻到云端数字化世界&#xff0c;能带来高沉浸式的逼真、震撼效果。 通过我们独特的漫游点自然场景过渡技术&#xff0c;您将置身于一个真…

开发个人Go-ChatGPT--5 模型管理 (一)

开发个人Go-ChatGPT–5 模型管理 (一) 背景 开发一个chatGPT的网站&#xff0c;后端服务如何实现与大模型的对话&#xff1f;是整个项目中开发困难较大的点。 如何实现上图的聊天对话功能&#xff1f;在开发后端的时候&#xff0c;如何实现stream的响应呢&#xff1f;本文就…

JRE、JVM、JDK分别是什么。

JDK JDK的英文全称是Java Development Kit。JDK是用于制作程序和Java应用程序的软件开发环境。JDK 是 Java 开发工具包&#xff0c;它是 Java 开发者用来编写、编译、调试和运行 Java 程序的集合。JDK 包括了 Java 编译器&#xff08;javac&#xff09;、Java 运行时环境&…

SLAM相关知识

目前在SLAM上的传感器主要分为两大类&#xff1a;激光雷达和摄像头 激光雷达&#xff1a;单线、多线 摄像头&#xff1a;单目相机&#xff08;普通USB相机&#xff09;、双目相机&#xff08;2个普通的USB相机&#xff09;、单目结构光&#xff08;深度相机&#xff09;、双目…

编辑器 goland 和 visual studio code

goland 编辑器做的真是太好了&#xff0c;面向 go 代码的定制设计&#xff0c;但它是收费软件&#xff0c;价格还贵的超出了自己的经济能力范围。有时候想打几行代码&#xff0c;却没有趁手的兵器&#xff0c;真是难受。但求助免费破解版吧&#xff0c;又需要关注公众号&#x…

用流式数据库解决「自动化检测服务器性能异常」难题

对 DevOps 团队来说&#xff0c;检测大量服务器的性能异常并尽快响应一直是个挑战。他们设置了各种指标来监控服务器性能&#xff0c;但诊断性能问题复杂且耗时&#xff0c;因为诊断数据的量可能非常大。越来越多的人认为这个过程应该自动化。但怎么做呢&#xff1f; 流式系统…

@Slf4j idea标红Cannot resolve symbol ‘log‘

一、背景 时间久了没有应用idea,打开工程后项目 log 提示报红&#xff0c;未能解析&#xff0c;Cannot resolve symbol log &#xff0c;Slf4j 注解正常&#xff0c;应用的lombok插件。 检查lombok插件安装情况&#xff0c;发现未安装&#xff0c;重新安装重启idea后正常。 二…

pdf容量大小怎么改,pdf容量太大怎么变小

在数字化时代&#xff0c;pdf文件因其稳定性和跨平台兼容性而成为工作、学习和生活中不可或缺的文件格式。然而&#xff0c;随着文件内容的丰富&#xff0c;pdf文件的体积也日益增大&#xff0c;给存储和传输带来了不少困扰。本文将为你详细介绍多种实用的pdf文件压缩方法&…

怎样在 PostgreSQL 中优化对 UUID 数据类型的索引和查询?

文章目录 一、UUID 数据类型概述二、UUID 索引和查询的性能问题三、优化方案&#xff08;一&#xff09;选择合适的索引类型&#xff08;二&#xff09;压缩 UUID&#xff08;三&#xff09;拆分 UUID&#xff08;四&#xff09;使用覆盖索引&#xff08;五&#xff09;优化查询…

AutoHotKey自动热键(五)添加WINDOWS秘笈指令-输入瞬间启动功能

在AUTOHOTKEY的使用中,不仅仅可以监听组合热键,还可以监听正常文本击键录入,这是另一种监听方式,比如依次击键jsq之后直接弹出<计算器>工具,或者依次击键sj之后直接输出135****5564的手机号码,等等,这就是autohotkey的录入击键监听,以双冒号为开头:: 因这种录入监听像极了…

Vue3使用ref绑定组件获取valueRef.value为null的解决

问题&#xff1a; onMounted(() > {nextTick(()>{console.log(treeselectRef, treeselectRef.value);console.log(treeselectRef.value, treeselectRef.value);}); });输出&#xff1a; 查看绑定和定义都没有问题&#xff0c;还是获取不到 解决&#xff1a;使用getCur…

transformer网络学习

Transformer encoder-decoder模型之间共享的是Encoder最后一层输出的hidden-state。 GitHub - huggingface/transformers: &#x1f917; Transformers: State-of-the-art Machine Learning for Pytorch, TensorFlow, and JAX. Bert2Bert中&#xff0c;Encoder的hidden-state同…

变阻器的分类

变阻器作为用于调节电路中电阻值的电子元件&#xff0c;在电子电路中具有广泛的应用。根据不同的工作原理和结构形式&#xff0c;变阻器可以分为多种类型。以下是对变阻器分类的详细阐述&#xff1a; 一、按工作原理分类 电位器是一种通过滑动端位置调节电阻值的变阻器&#x…

移动公厕有无人显示屏为何多采用RS485、IO信号通讯方式

在户外活动、临时集会或是应急情况下&#xff0c;移动公厕作为解决人们生理需求的重要设施&#xff0c;发挥着不可替代的作用。然而&#xff0c;随着人口密度的增加和对公共卫生要求的提高&#xff0c;如何确保移动公厕的高效利用和良好维护&#xff0c;成为了组织者和管理者面…