欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

Linux进程的零基础学习笔记

时间:2023-06-24
文章目录

进程的由来

程序进程查看进程之间的关系操作系统如何区分进程 创建一个新进程

fork函数fork函数特性fork函数要点总结 子进程的偷梁换柱

exec函数族要点总结 进程的退出

正常退出:exit() 和 _exit() 退出函数exit() 和 _exit() 两者的区别 等待子进程的终结

wait函数处理子进程退出状态值的宏 进程的生老病死

进程状态: 进程组、会话、终端

进程组进程组的诞生会话会话的诞生前台进程组后台进程组终端 守护进程

守护进程如何来写一个守护进程 PS命令详解

ps auxps axjf使用场景 僵尸进程和托孤进程

僵尸进程托孤进程 什么是进程间通信(ipc)

进程间通信Linux系统下的ipc 无名管道

pipe 函数特点使用步骤 有名管道

mkfifo函数特点使用步骤 信号简介

信号的基本概念怎么产生信号?信号的处理方式 常用信号分析signal_kill_raise 函数

signal函数kill 函数raise函数 信号集处理函数

屏蔽信号集未处理信号集 system-V 消息队列

system-V ipc特点消息队列用法ftok函数msgget函数msgsnd 函数msgrcv函数msgctl 函数 system-V 信号量

本质作用semget 函数semctl函数semop system-V 共享内存

作用共享内存用法shmget函数shmat函数shmdt 函数shmctl函数 进程的由来 程序

静态文件

进程

运行着的实体

查看进程之间的关系

pstree

操作系统如何区分进程

PID:进程的身份证

创建一个新进程 fork函数

头文件:

#include

函数原型:

pid_t fork(void);

返回值:

成功:0或其他正整数
失败:-1

fork函数特性

执行fork函数之后,会返回两次在旧进程中返回,返回值为0在新进程返回时,返回值为进程的pid

所以叫做复制一个进程更加贴切

fork函数要点总结

在执行fork函数之前,操作系统只有一个进程,fork函数之前的代码只会被执行一次。

在执行fork函数之后,操作系统有两个几乎一样的进程,fork函数之后的代码会被执行两次。

子进程的偷梁换柱 exec函数族

常用后缀:

l: 代表以列表形式传参
v:代表以矢量数据形式传参
p:代表使用环境变量Path来寻找指定执行文件
e:代表用户提供自定义的环境变量

头文件:

#include

函数原型:

int execl(const char *path,const char *arg, …)

int execlp(const char *file, const char *arg, …)

int execv(const char *path,char *const argv[])

int execve(const char *path, char *const argv[], char *const envp[])

返回值

成功:不返回
失败:-1

要点总结

l 后缀和 v 后缀必须两者选其一来使用p 后缀和 e 后缀是可选的,可用可不用组合后缀的相关函数还有很多,可自己进一步了解

exce函数有可能执行失败,需要预防

新程序的文件路劲出错传参或者是自定义环境变量时,后面没有加 NULL新程序没有执行权限 进程的退出 正常退出:

从main 函数 return调用 exit() 函数终止调用 _exit() 函数终止 exit() 和 _exit() 退出函数

头文件:

#include
#include

原型:

void _exit(int status);
void exit(int status);

返回值:

不返回

exit() 和 _exit() 两者的区别

_exit() 直接退出
exit() 将文本缓存处理完才退出

等待子进程的终结 wait函数

头文件

#include

函数原型

pid_t wait(int *status)

返回值

成功:退出的子进程的pid
失败:-1

处理子进程退出状态值的宏

WIFEXITED(status):如果子进程正常退出,则宏为真WEXITSTATUS(status):如果子进程正常退出,则该宏获取子进程的退出值 进程的生老病死 进程状态:

TASK_RUNNING:就绪/运行状态TASK_INTERRUPTIBLE:可中断睡眠状态TASK_UNINTERRUPNBLE:不可中断睡眠状态TASK_TRACED:调试态TASK_STOPPED:暂停状态EXIT_ZOMBIE:僵死状态EXIT_DEAD:死亡态
进程组、会话、终端 进程组

作用:对相同类型的进程进行管理

进程组的诞生

在 shell 里面直接执行一个应用程序,对于大部分进程来说,自己就是进程的首进程,进程组只有一个进程如果进程调用了 fork 函数,那么父子进程同属一个进程组,父进程为首进程在 shell 中通过管道执行连接起来的应用程序,两个程序同属一个进程组,第一个程序为进程组的首进程

进程组 id :pgid,由首进程 pid 决定

会话

作用:管理进程组

会话的诞生

调用 setsid 函数,新建一个会话,应用程序作为会话的第一个进程,称为会话首进程用户在终端正确登陆之后,启动 shell 时 linux 系统会创建一个新的会话,shell 进程作为会话首进程

会话 id:会话首进程 id,SID

前台进程组

shell 进程启动时,默认是前台进程组的首进程。前台进程组的首进程会占用会话所关联的终端来运行,shell 启动其他应用程序时,其他程序成为首进程 后台进程组

后台进程中的程序是不会占用终端在 shell 进程里启动程序时,加上 & 符号可以指定程序运行在后台进程组里面

ctrl + z:可以将程序运行在后台进程组中
jobs:查看有哪些后台进程组
fg+job id:可以把后台进程组切换为前台进程组

终端

物理终端

串口终端lcd 终端 伪终端

ssh远程连接产生的终端桌面系统启动的终端 虚拟终端

Linux 内核自带的,ctrl +alt+f0~f6可以打开7个虚拟终端 守护进程

会话用来管理的后台进程组
会话一般关联着一个终端
当终端被关闭了之后,会话中的所有进程都会被关掉

守护进程

不受终端影响,就算终端退出,也可以继续在后台运行

如何来写一个守护进程

步骤:

创建一个子进程,父进程直接退出
方法:通过 fork() 函数创建一个新的会话,摆脱终端的影响
方法:通过 setsid() 函数改变守护进程的当前工作目录,改为 “/”
方法:通过 chrdir() 函数重设文件权限掩码
新建文件的权限受文件权限掩码影响
uamsk:022,000010010,只写
新建文件默认执行权限:666, 110110110
真正的文件执行权限:666&~umask
方法:通过 umask() 函数关闭不需要的文件描述符
0,1,2:标准输入、输出、出错
方法:通过 close() 函数

普通进程伪装成守护进程:
nohup

PS命令详解

aux
axjf

a: 显示一个终端所有的进程u:显示进程的归属用户及内存使用情况x:显示没有关联控制终端的进程j:显示进程归属的进程 id,会话 id,父进程 idf:以 ascii 形式显示出进程的层次关系 ps aux

user:进程是哪个用户产生的pid:进程的身份证号码%cpu:表示进程占用了 cpu 计算能力的百分比%mem:表示进程占用了系统内存的百分比vsz:进程使用的虚拟内存大小rss:进程使用的物理内存大小tty:表示进程关联的终端stat:表示进程当前状态start:表示进程的启动时间time:记录进程的运行时间command:表示进程执行的具体程序 ps axjf

ppid:表示进程的父进程idpid:进程的身份证号码pgid:进程所在进程组的idsid:进程所在会话的idtty:表示进程关联的终端tpgid:值位-1,表示进程为守护进程stat:表示进程当前状态uid:启动进程的用户idtime:记录进程的运行时间command:表示进程的层次关系 使用场景

关注进程本身:ps aux
关注进程间的关系:ps axjf

僵尸进程和托孤进程

进程的正常退出步骤:

子进程调用 exit() 函数退出父进程调用 wait() 函数为子进程处理其他事情 僵尸进程

子进程退出后,父进程没有调用 wait() 函数处理身后事,子进程变成僵尸进程

托孤进程

父进程比子进程先退出,子进程变为孤儿进程,Linux系统会把子进程托孤给 1 号进程( init 进程)

什么是进程间通信(ipc) 进程间通信

数据传输资源共享事件通知进程控制 Linux系统下的ipc

早期 unix 系统 ipc

管道信号fifo system-v ipc(贝尔实验室)

system-v 消息队列system-v 信号量system-v 共享内存 socket ipc(BSD)posix ipc(IEEE)

posix 消息队列posix 信号量posix 共享内存 无名管道 pipe 函数

头文件:

#include

函数原型:

int pipe(int pipefd[2]);

返回值:

成功:0
失败:-1

特点

特殊文件(没有名字),无法使用 open 函数打开,但是可以使用 close 函数。只能通过子进程继承文件描述符的形式来使用write 和 read 操作可能会阻塞进程所有文件描述符被关闭之后,无名管道被销毁 使用步骤

父进程 pipe 无名管道fork 子进程close 无用端口write/read 读写端口close 读写端口 有名管道 mkfifo函数

头文件:

#include
#include

函数原型:

int mkfifo(const char *filename,mode_t mode)

返回值:

成功:0
失败:-1

特点

有文件名,可以使用 open 函数打开任意进程间数据传输write 和 read 操作可能会阻塞进程write 具有“原子性” 使用步骤

第一个进程 mkfifo 有名管道open 有名管道,write/read 数据close 有名管道第二个进程 open 有名管道,read/ write 数据close 有名管道 信号简介 信号的基本概念

软件模拟中断,进程接受信号后,做出相应响应

怎么产生信号?

硬件

执行非法指令访问非法内存驱动程序…… 软件

控制台:

ctrl+c:中断信号ctrl+c:退出信号ctrl+c:停止信号 kill 命令程序调用 kill() 函数 信号的处理方式

忽略:进程当信号从来没有发生过捕获:进程会调用相应的处理函数,进行相应的处理默认:使用系统默认处理方式来处理信号 常用信号分析 信号名信号编号产生原因默认处理方式SIGHUP1关闭终端终止SIGINT2ctrl+c终止SIGQUIT3ctrl+终止+转储SIGABRT6abort()终止+转储SIGPE8算术错误终止SIGKILL9kill -9 pid终止,不可捕获/忽略SIGUSR110自定义忽略SIGSEGV11段错误终止+转储SIGUSR212自定义忽略SIGALRM14alarm()终止SIGTERM15kill pid终止SIGCHLD17(子)状态变化忽略SIGTOP19ctrl+z暂停,不可捕获/忽略

pkill 命令:制定杀死某一类进程

signal_kill_raise 函数 signal函数

头文件:

#include

函数原型:

typedef void (*sighandler_t)(int);
sighandler_t signal(int aignum, sighandler_t handler);

参数:

signum:要设置的信号handler:

SIG_IGN:忽略SIG_DFL:默认void (*sighandler_t)(int):自定义

返回值:

成功:上一次设置的handler
失败:SIG_ERR

kill 函数

头文件:

#include
#include

原型函数:

int kill(pid_t pid,int sig)

参数:

pid:进程idsig:要发送的信号

返回值:

成功:0
失败:-1

raise函数

头文件:

#include

函数原型:

int raise(int sig);

参数:

sig:发送信号

函数返回值:

成功:0
失败:非0

信号集处理函数 屏蔽信号集

屏蔽某些信号

手动自动 未处理信号集

信号如果被屏蔽,则记录在未处理信号集中

非实时信号(1-31),不排队,只留一个实时信号(34-64),排队,保留全部

信号集相关API

int sigemptyset(sigset_t *set);

将信号集合初始化为 0 int sigfillset(sigset_t *set);

将信号集合初始化为 1 int sigaddset(sigset_t *set, int signum);

将信号集合某一位设置为 1 int sigdelset(sigset_t *set, int signum);

将信号集合某一位设置为 0 int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

使用设置好的信号集去修改信号屏蔽集参数 how:

SIG_BLOCK:屏蔽某个信号(屏蔽集 | set)SIG_UNBLOCK:打开某个信号(屏蔽集 & (~set))SIG_SETMASK:屏蔽集 = set 参数 oldset:保存旧的屏蔽集的值,NULL表示不保存 system-V 消息队列 system-V ipc特点

独立于进程没有文件名和文件描述符IPC对象有 key 和 ID 消息队列用法

定义一个唯一 key (ftok)构造消息对象(msgget)发送特定类型消息(msgsnd)接受特定类型消息(msgrcv)删除消息队列(msgctl) ftok函数

功能:获取一个 key
函数原型:

key_t ftok(const char *path, int proj_id)

参数:

path:一个合法路径proj_id:一个整数

返回值:
成功:合法键值
失败:-1

msgget函数

功能:获取消息队列ID
函数原型:

int msgget(key_t key, int msgflg)

参数:

key:消息队列的键值msgflg:

IPC_CREAT:如果消息队列不存在,则创建mode:访问权限

返回值:
成功:该消息队列的ID
失败:-1

msgsnd 函数

功能:发送消息到消息队列
函数原型:

int msgsnd(int msgid, const void *msgp, size_t msgsz,int msgflg);

参数:

msqid:消息队列IDmsgp:消息缓存区

struct msgbuf
{
long mtype; //消息标识
char mtext[1]; //消息内容
} msgsz:消息正文的字节数msgflg:

IPC_NOWAIT:非阻塞发送0:阻塞发送

返回值:
成功:0
失败:-1

msgrcv函数

功能:从消息队列读取消息
函数原型:

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)

参数:

msqid:消息队列 IDmsgp:消息缓存区msgsz:消息正文的字节数msgtyp:要接受消息的标识msgflg:

IPC_NOWAIT:非阻塞读取MSG_NOERROR:截断消息0:阻塞读取
返回值:
成功:0
失败:-1 msgctl 函数

功能:设置或获取消息队列的相关属性
函数原型:

int msgctl(int msgqid,int cmd,struct maqid_ds *buf)

msgqid:消息队列的IDcmd

IPC_STAT:获取消息队列的属性信息IPC_SET:设置消息队列的属性IPC_RMID:删除消息队列 buf:相关结构体缓冲区 system-V 信号量 本质

计数器

作用

保护共享资源

互斥同步

信号量用法

定义一个唯一 key (fork)构造一个信号量(semget)初始化信号量(semctl SETVA)对信号量进行 P/V 操作(semop)删除信号量(semctl RMID) semget 函数

功能:获取信号量的ID
函数原型:

int semget(key_T key,int nsems,int semflg)

参数:

key:信号量键值nsems:信号量数量semflg:

IPC_CREATE:信号量不存在则创建mode:信号量的权限

返回值:
成功:信号量ID
失败:-1

semctl函数

功能:获取或设置信号量的相关属性
函数原型:

int semctl(int semid, int semnum, int cmd,union semun arg)

参数:

semid:信号量IDsemnum:信号量编号cmd:

IPC_STAT:获取信号量的属性信息IPC_SET:设置信号量的属性IPC_RMID:删除信号量IPC_SETVAL:设置信号量的值 arg:
union semun
{
int val;
struct semid_ds *buf;
}

返回值:
成功:由 cmd 类型决定
失败:-1

semop

函数原型:

int semop(int semid,struct sembuf *sops,size_t nsops)

参数:

semid:信号量IDsops:信号量操作结构体数组
struct sembuf
{
short sem_num; //信号量编号
short sem_op; //信号量P/V操作
short sem_flg; //信号量行为,SEM_UNDO
}nsops:信号量数量

返回值:
成功:0
失败:-1

system-V 共享内存 作用

高效率传输大量数据

共享内存用法

定义一个唯一key(fork)构造一个共享内存对象(shmget)共享内存映射(shmat)解除共享内存映射(shmdt)删除共享内存(shmctl RMID) shmget函数

功能:获取共享内存对象的ID
函数原型:

int shmget(key_t key, int size, int shmflg)

参数:

key:共享对象键值nsems:共享内存大小shmflg:

IPC_CREATE:共享内存不存在则创建mode:共享内存的权限

返回值:
成功:共享内存ID
失败:-1

shmat函数

功能:映射共享内存
函数原型:

int shmat(int shmid, const void *shmaddr, int shmflg)

参数:

shmid:共享内存IDshmaddr:映射地址,NULL为自动分配shmflg:

SHM_RDONLY:只读方式映射0:可读可写

返回值:
成功:共享内存首地址
失败:-1

shmdt 函数

功能:解除共享内存映射
函数原型:

int shmdt(const void *shmaddr)

参数:
shmaddr:映射地址

返回值:
成功:0
失败:-1

shmctl函数

功能:获取或设置共享内存的相关属性
函数原型:

int shmctl(int shmid, int cmd, struct shmid_ds *buf)

参数:

shmid:共享内存IDcmd:

IPC_STAT:获取共享内存的属性信息IPC_SET:设置共享内存的属性IPC_RMID:删除共享内存 buf:属性缓冲区

返回值:
成功:由 cmd 类型决定
失败:-1

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。