当前位置: 代码迷 >> 综合 >> 嵌入式开发第24天(线程参数,进程,线程,fork,exit,waitpid,exec)
  详细解决方案

嵌入式开发第24天(线程参数,进程,线程,fork,exit,waitpid,exec)

热度:4   发布时间:2023-12-12 13:06:03.0

线程参数

ps -Af

短格式         长格式             说 明
c cmd 可执行的简单名称
C cmdline 完整命令行
f flags 长模式标志
g pgrp 进程的组ID
G tpgid 控制tty进程组ID
j cutime 累计用户时间
J cstime 累计系统时间
k utime 用户时间
K stime 系统时间
m min_flt 次要页错误的数量
M maj_flt 主要页错误的数量
n cmin_flt 累计次要页错误
N cmaj_flt 累计主要页错误
o session 对话ID
p pid 进程ID
P ppid 父进程ID
r rss 驻留大小
R resident 驻留页
s size 内存大小(千字节)
S share 共享页的数量
t tty tty次要设备号
T start_time 进程启动的时间
U uid UID
u user 用户名
v vsize 总的虚拟内存数量(字节)
y priority 内核调度优先级


ps -ef出来后

init PPID 为0的进程为系统磁盘的就已经存在生成   

//通过实验发现 kill -9  0为退出状态(ctrl +d)

//而杀不死0 这个进程


kthreadd:为守护进程

top:

PID 每个进程的ID。
PPID 每个进程的父进程ID。
UID 每个进程所有者的UID 。
USER 每个进程所有者的用户名。
PRI 每个进程的优先级别。
NI 该进程的优先级值。
SIZE 该进程的代码大小加上数据大小再加上堆栈空间大小的总数。单位是KB。
TSIZE 该进程的代码大小。对于内核进程这是一个很奇怪的值。
DSIZE 数据和堆栈的大小。
TRS 文本驻留大小。
D 被标记为“不干净”的页项目。
LIB 使用的库页的大小。对于ELF进程没有作用。
RSS 该进程占用的物理内存的总数量,单位是KB。
SHARE 该进程使用共享内存的数量。
STAT 该进程的状态。
其中S代表休眠状态;
D 代表不可中断的休眠状态;
R 代表运行状态;
Z 代表僵死状态;

T 代表停止或跟踪状态。

--------------------------------------------------------------------------------------------------------------------

1、进程、线程、进程间通信(ipc)


程序:存储在磁盘里面的二进制文件
进程:执行中的程序(内存)
官方说法:
进程是正在运行的程序的实例
进程是一个具有独立功能的程序关于某个数据集合的一次运行活动
是系统进行资源分配和调度的基本单位,是操作系统结构的基础
是一个动态的概念,是一个活动的实体
进程是由进程控制块PCB、程序段、数据段三部分组成
进程控制块PCB


$vi /usr/src/linux-headers-3.5.0-23-generic/include/linux/sched.h   (1229行)

相关命令

pstree --查看进程树
ps -Af查看进程树的详细信息
init 是linux里面所有的进程的祖进程 ,1号进程
top(查看动态进程)


创建进程fork():

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


返回值:   0   表示成功创建子进程
>0 表示返回值给父进程
=-1   表示创建进程失败


获取进程的ID
       #include <sys/types.h>
       #include <unistd.h>

        pid_t getpid(void);//获取自己的ID
      pid_t getppid(void);//获取父进程的ID


进程运行状态


进程的执行:父子进程的执行顺序是随机,不一定是父进程先于子进程。


僵尸进程:一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他, 那么他将变成一个僵尸进程。

孤儿进程:   父进程已经结束后的子进程,会由init 1号进程接管,所以该进程ppid是1
     init接管后,在该进程结束时候,负责“收尸”,回收系统资源和进程信息

避免僵尸进程:
让父进程回收子进程资源


       #include <sys/wait.h>

       pid_t wait(int *stat_loc);

返回值:   成功:返回被成功回收资源的子进程的PID;
失败:-1
       
int *stat_loc:存放子进程退出的状态。// 一共32位 ,仅有后八位存放 exit返回值,其他 都是存放退出状态,可以用对应宏来获取exit返回值 ; WEXITSTATU(star_loc)
功能:

  等待任意一个子进程结束,
  会令本进程进入阻塞,
  wait得到回收资源完成的信号后,才结束阻塞


waitpid();   //当一个父进程有多个子进程时调用这个,他可以等待指定进程

#include <sys/wait.h>

pid_t waitpid(pid_t pid, int *stat_loc, int options);
pid_t pid:  < -1 等待的是pid对应的进程组中的任意一个子进程
  = -1 等待任意一个子进程
   = 0 等待的是本进程组中的任意一个子进程
  > 0 等待进程ID为pid的子进程


int *stat_loc:存放子进程退出的状态。
int options:
WCONTINUED:当没有已退的子进程时立即返回(阻塞)
WNOHANG:   当有子进程被暂时时立即返回
WUNTRACED: 当子进程收到继续信号即立即返回


exit() _exit();

exit_exit函数用于正常终止一个程序(另外一个方法是从main函数中返回),它们可以用于子程序中。


1.exit函数

使用exit函数,要包含头文件”stdlib.h”

函数的使用形式为”void exit(int status)”


2._exit函数

使用_exit函数,须包含“unistd.h”头文件

函数形式为”void _exit(int status)”


综上所述,exit函数和_exit函数有如下区别:

1> exit函数在ANSIC中说明的,而_exit函数是在POSIX标准中说明

2> exit函数将终止调用进程,在退出程序之前所有文件被关闭,

标准输入输出的缓冲区被清空,并执行在atexit注册的回调函数;


_exit函数终止调用进程,但不关闭文件,不清除标准输入输出的缓冲区,

也不调用在atexit注册的回调函数。


exec():  //常用于父子分别在对应的代码段占用的空间太多而,调用

//在父子进程里面  其实是父子程序的代码是相同的,
//所以在子进程里也有父进程对应的代码段,为了省下父进程的对应代码空间
//使用exec来调用写好的文件,而且exec调用的文件还会清空 下面的代码,意思就是,使用exec调用程序后,子进程下的东西都会清空

功能:执行一个文件语法
#include <unistd.h>
int execve(const char* path, char* const* argv,char* const* envp);

int execl(const char* path, char* arg,...); //带程序参数的调用

int execp(const char* file, char* arg,...);//环境变量   如  cat   ls  等~
int execle(const char* path, const char* argv,...,char* const* envp);

int execv(const char* path, char* const* arg);  //写好参数数组的  带程序参数调用

int execvp(const char* file, char* const* arg);


说明:

     exec 函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内
容,换句话说,就是在调用进程内部执行一个可执行文件

     其中只有 execve 是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。


与一般情况不同,exec 函数族的函数执行成功后不会返回,因为调用进程的实体,包
括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程 ID 等一些表面上的信息仍
保持原样,颇有些神似"三十六计"中的"金蝉脱壳"。看上去还是旧的躯壳,却已经注入了新
的灵魂。只有调用失败了,它们才会返回一个-1,从原程序的调用点接着往下执行。
fork()和 exec()这两个函数,前者用于并行执行,父、子进程执行相同正文中的不同
部分;后者用于调用其他进程,父、子进程执行不同的正文,调用前,一般应为子进程创造
一个干净的环境

fork()以后,父、子进程共享代码段,并只重新创建数据有改变的页(段页式管理)      exec()以后,建立新的代码段,用被调用程序的内容填充。       

前者的子进程执行后续的公共代码,后者的子进程不执行后续的公共代码。
      父、子进程以及各个子进程执行的顺序不定。
例子:

printf("now this process will be ps command\n");
     execl("/bin/ps","ps","-ef",NULL);




















  相关解决方案