广州工程建设网站,华为应用商店下载,城乡与建设部网站,怎么制作小游戏文章目录 进程以及状态进程进程的状态linux下的进程管理pstopbgkillcrontab 进程的创建两个while同时运行示例获取进程pidProcess 结构给子进程指定的函数传递参数进程间是否共享全局变量补充 进程间通信-Queue常用操作Queue 实例 管道通信#xff08;了解#xff09;样例 进… 文章目录 进程以及状态进程进程的状态linux下的进程管理pstopbgkillcrontab 进程的创建两个while同时运行示例获取进程pidProcess 结构给子进程指定的函数传递参数进程间是否共享全局变量补充 进程间通信-Queue常用操作Queue 实例 管道通信了解样例 进程池 Pool进程池中的Queue 示例文件夹 copy 器多进程 进程以及状态
进程
进程一个程序运行起来后代码用到的资源 称之为进程它是操作系统分配资源的基本单元。资源包括Cpu内存文件socket 对象等等
进程的状态 操作系统内核实际上采用时间片轮转的方式进行调控进程的运行也就是在内核分配中实际上是存在进程队列 和 睡眠队列前者好比程序运行了一个时间片就移到下一个进程周期中然后到达下一个进程周期时进行重新分配时间片后再接着运行而在进程运行的时候如果发现需要等待条件如input的时候就将这个进程调入睡眠队列。
R 状态 运行 S 状态 睡眠
常用的查看进程状态的命令top ps下文会详细介绍
而对于ps来说看到 R 状态是两次采样之间的一个时间片变化分析计算并不意味着他是处于运动状态意思是他在一个时间片两次采样之间存在运动状态
linux下的进程管理
常用的相关指令
命令含义ps查看系统中的进程top动态显示系统中的进程kill向进程发送信号包括后台进程crontab用于安装删除或者列出用于驱动cron后台进程的任务bg将挂起的进程放到后台执行
备注
cat /proc/cpuinfo 查看 Linux 的 cpu 的核数进程 process是 os 的最小单元 os 会为每个进程分配大小为 4g 的虚拟内存空间其中1g 给内核空间 3g 给用户空间代码区 数据区 堆栈}python main.py 让进程在后台运行
ps
ps –elf 可以显示父子进程关系基本上用这个就可以了加上|grep 进行筛选相关的想查看的进程 补充
进程的状态包括四种S 睡眠input T 暂停ctrlz单步调试R 运行正常python运行 Z僵尸
top
top 显示前 20 条进程动态的改变按 q退出
运行出来是这样子的
top - 16:24:25 up 284 days, 4:59, 1 user, load average: 0.10, 0.05, 0.01
Tasks: 115 total, 1 running, 114 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.1%us, 0.0%sy, 0.0%ni, 99.8%id, 0.0%wa, 0.0%hi, 0.1%si, 0.0%st
Mem: 4074364k total, 3733628k used, 340736k free, 296520k buffers
Swap: 2104504k total, 40272k used, 2064232k free, 931680k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME COMMAND
11836 root 15 0 2324 1028 800 R 0.3 0.0 0:00.02 top
27225 root 25 0 1494m 696m 11m S 0.3 17.5 2304:03 java
1 root 18 0 2072 620 532 S 0.0 0.0 7:04.48 init下面介绍一下是什么意思
第一行
16:24:25 当前时间
up 284 days, 4:59 系统启动时间
1 user 当前系统登录用户数目# 重要
load average: 0.10, 0.05, 0.01 平均负载1 分钟,10 分钟,15 分钟
平均负载load average,一般对于单个 cpu 来说负载在 01.00 之间是正常的超过 1.00 须引起注意。在多核 cpu 中系统平均负载不应该高于 cpu 核心的总数太多
第二行
115 total 进程总数、
1 running 运行进程数、
114 sleeping 休眠进程数、
0 stopped 终止进程数、
0 zombie 僵死进程数第三行
# 重要 用户空间实际上就是比如我们采用for循环的打印这类的在端口上打印数据之类的操作
0.1%us %us 用户空间占用 cpu 百分比# 重要 内核空间大部分在于调用资源的占比 也就是在Flood DDos攻击下主要攻击的地方
0.0%sy %sy 内核空间占用 cpu 百分比0.0%ni %ni 用户进程空间内改变过优先级的进程占用 cpu 百分比# 重要
99.8%id %id 空闲 cpu 百分比反映一个系统 cpu 的闲忙程度。越大越空闲0.0%wa %wa 等待输入输出I/O的 cpu 百分比
0.0%hi %hi 指的是 cpu 处理硬件中断的时间
0.1%si %si 值的是 cpu 处理软件中断的时间
0.0%st %st 用于有虚拟 cpu 的情况用来指示被虚拟机偷掉的 cpu 时间。
第四行Mem
4074364k total total 总的物理内存
3733628k used used 使用物理内存大小
340736k free free 空闲物理内存
296520k buffers buffers 用于内核缓存的内存大小查看系统内存占用情况 也可以使用free命令
第五行Swap
2104504k total total 总的交换空间大小
40272k used used 已经使用交换空间大小
2064232k free free 空间交换空间大小
931680k cached cached 缓冲的交换空间大小然后下面就是和 ps 相仿的各进程情况列表了 第六行
PID 进程号USER 运行用户PR 优先级PR(Priority)优先级NI 任务 nice 值VIRT 进程使用的虚拟内存总量单位 kb。VIRTSWAPRESRES 物理内存用量SHR 共享内存用量 S 该进程的状态。其中 S 代表休眠状态D 代表不可中断的休眠状态R 代表运行状态Z 代表僵死状态T 代表停止或跟踪状态%CPU 该进程自最近一次刷新以来所占用的 CPU 时间和总时间的百分比%MEM 该进程占用的物理内存占总内存的百分比TIME 累计 cpu 占用时间 11.COMMAND 该进程的命令名称如果一行显示不下则会进行截取。内存中的进程会有一个完整的命令行。
bg
bg 让暂停的进程在后台运行 fg 拉到前台 jobs 看后台任务
$ python main.py
^Z
[1] 已停止 main.py$ jobs
[1] 已停止 main.py$ python main.py
[2] 4616 $ jobs
[1] 已停止 python main.py
[2]- 运行中 python main.py # bg就是让这里通过ctrlz暂停执行的代码重新后台跑起来 1是对应的这个id号
$ bg 1
[1] python main.py $ jobs
[1] 运行中 python main.py
[2]- 运行中 python main.py # 实际上就是把后台运行的代码拉到前台运行
$ fg 2
python main.py
kill
kill -l 查看系统的所有信号 kill -9 进程号 表示向某个进程发送 9 号信号从而杀掉某个进程
利用 pkill -f a 可以杀死进程名为 a 的进程,如果有空格用\转义 pkill -f python\ 1.while 死循环.p
crontab
crontab –e 设置当前用户定时任务 vim /etc/crontab 设置定时任务 crontab -l 查看当前自己设置的定时任务
详细见链接
进程的创建
multiprocessing 模块就是跨平台版本的多进程模块提供了一个 Process 类来代表一个进程对象这个对象可以理解为是一个独立的进程可以执行另外的事情
两个while同时运行示例
from multiprocessing import Process
import timedef run_proc():子进程要执行的代码while True:print(----2----)time.sleep(1)if __name____main__:p Process(targetrun_proc)p.start()while True:print(----1----)time.sleep(1)对于这个程序来说实际上是先python运行得到一个父进程然后这个父进程通过process生成一个子进程然后两个进程之间相互时间片轮转运行。
获取进程pid
from multiprocessing import Process
import os
import timedef run_proc():子进程要执行的代码print(子进程运行中pid%d... % os.getpid()) # os.getpid 获取当前进程的进程号print(子进程将要结束...)if __name__ __main__:print(父进程 pid: %d % os.getpid()) # os.getpid 获取当前进程的进程号p Process(targetrun_proc)p.start()获取父亲的 pid os.getppid() # 多个p而对父进程的使用os.getppid()得到的pid是bash命令行的pid
Process 结构
Process(group , target , name , args , kwargs) • target如果传递了函数的引用可以让这个子进程就执行这里的代码 • args给 target 指定的函数传递的参数以元组的方式传递 • kwargs给 target 指定的函数传递命名参数keyword 参数 • name给进程设定一个名字可以不设定 • group指定进程组大多数情况下用不到Process 创建的实例对象的常用方法 • start()启动子进程实例创建子进程 • is_alive()判断进程子进程是否还在活着 • join([timeout])是否等待子进程执行结束或等待多少秒回收子进程尸体实际上这个很重要。 • terminate()不管任务是否完成立即终止子进程Process 创建的实例对象的常用属性 • pid当前进程的 pid进程号
给子进程指定的函数传递参数
from multiprocessing import Process
import os
from time import sleepdef run_proc(name, age, **kwargs):for i in range(10):print(子进程运行中name %s,age%d ,pid%d... % (name, age, os.getpid()))print(kwargs)sleep(0.2)if __name____main__:# 这边是关键 args 和 kwargsp Process(targetrun_proc, args(test,18), kwargs{m:20})p.start()sleep(1) # 1 秒中之后立即结束子进程p.terminate()p.join()进程间是否共享全局变量
from multiprocessing import Process
import os
import timenums [11, 22]def work1():子进程要执行的代码print(in process1 pid%d ,nums%s % (os.getpid(), nums))for i in range(3):nums.append(i)time.sleep(1)print(in process1 pid%d ,nums%s % (os.getpid(), nums))def work2():子进程要执行的代码print(in process2 pid%d ,nums%s % (os.getpid(), nums))if __name__ __main__:p1 Process(targetwork1)p1.start()p1.join()p2 Process(targetwork2)p2.start()好好理解一下实际上对于num参数来说创建子进程的时候会复制一份父进程的资源而二者的资源独立使用对于num是何值取决于创建子进程的那一瞬间父进程的该项资源是什么值。
补充
孤儿进程 — 子进程在运行父进程先执行结束完退出此时通过ps -elf|grep 程序名称进行查看发现父进程进入等待wait状态子进程在运行然后此时kill 杀死父进程子进程变为孤儿进程。定义孤儿进程是指其父进程已经结束或者失去了对该进程的控制权而该进程仍然在运行的情况下被称为孤儿进程。但是对于python程序来说当孤儿进程出现的时候linux内核会将这个孤儿进程的父亲pid弄成1也就是开机进程此时此孤儿进程结束之后资源就由开机进程回收僵尸进程 — 子进程退出父进程在忙碌没有回收它要避免僵尸Python 进程变为僵尸进程后名字会改变所以如果想要查看僵尸进程的时候就需要查找对应进程的的pid或者直接ps -elf直接翻 并不能通过kill的方法杀死僵尸进程原因就在于实际上我们kill实现的功能就是通过将这个进程变成僵尸进程然后父亲进程马上就会回收子进程的资源也就是此时这个僵尸进程就会马上消失所以想要杀死一个僵尸进程就不能让父亲进程时刻处于忙碌状态。
进程间通信-Queue
常用操作
常用操作说明q Queue(number)括号中指定的数据是这个队列最大能容纳多少条的信息若括号中没有指定最大可接收的消息数量或数量为负值那么就代表可接受的消息数量没有上限直到内存的尽头Queue.qsize()返回当前队列包含的消息数量Queue.empty()如果队列为空返回 True反之 FalseQueue.full()如果队列满了返回 True,反之 FalseQueue.get([block[, timeout]])获取队列中的一条消息然后将其从队列中移除block 默认值为 TrueQueue.get_nowait()相当 Queue.get(blockFalse)Queue.put(item,[block[, timeout]])将 item 消息写入队列block 默认值为TrueQueue.put_nowait(item)相当 Queue.put(item, False
对于Queue.get([block[, timeout]])中 1如果 block 使用默认值且没有设置 timeout单位秒消息列队如果为空此时程序将被阻塞停在读取状态直到从消息列队读到消息为止如果设置了 timeout则会等待 timeout 秒若还没读取到任何消息则抛出“Queue.Empty”异常 2如果 block 值为 False消息列队如果为空则会立刻抛出Queue.Empty异常。对于Queue.put(item,[block[, timeout]]) 1如果 block 使用默认值且没有设置 timeout单位秒消息列队如果已经没有空间可写入此时程序将被阻塞停在写入状态直到从消息列队腾出空间为止如果设置了 timeout则会等待 timeout 秒若还没空间则抛出“Queue.Full”异常 2如果 block 值为 False消息列队如果没有空间可写入则会立刻抛抛出Queue.Full异常
Queue 实例
from multiprocessing import Process, Queue
import time
def writer(q):for value in [A, B, C]:print(Put %s to queue... % value)q.put(value)time.sleep(1)def reader(q:Queue):while True:if not q.empty():value q.get(True)print(Get %s from queue. % value)time.sleep(2)else:breakif __name__ __main__:qQueue(10)pwProcess(targetwriter,args(q,)) #一个元素必须加逗号才是元组prProcess(targetreader,args(q,))pw.start()time.sleep(1)pr.start()pw.join()pr.join()管道通信了解
此模块参考链接
Pipe 常用来实现 2 个进程之间的通信这 2 个进程分别位于管道的两端一端用来发送数据另一端用来接收数据。使用 Pipe 实现进程通信首先需要调用 multiprocessing.Pipe() 函数来创建一个管道。
conn1, conn2 multiprocessing.Pipe( [duplexTrue] )其中conn1 和 conn2 分别用来接收 Pipe 函数返回的 2 个端口duplex 参数默认为True表示该管道是双向的即位于 2 个端口的进程既可以发送数据也可以接受数据而如果将 duplex 值设为 False则表示管道是单向的conn1 只能用来接收数据而 conn2只能用来发送数据。
样例
from multiprocessing import Pipe, Processdef son_process(x, pipe):_out_pipe, _in_pipe pipe# 关闭fork过来的输入端_in_pipe.close()while True:try:msg _out_pipe.recv()print(msg)except EOFError:# 当out_pipe接受不到输出的时候且输入被关闭的时候会抛出EORFError可以捕获并且退出子进程breakif __name__ __main__:out_pipe, in_pipe Pipe(True)son_p Process(targetson_process, args(100, (out_pipe, in_pipe)))son_p.start()# 等 pipe 被 fork 后关闭主进程的输出端# 这样创建的Pipe一端连接着主进程的输入一端连接着子进程的输出口out_pipe.close()for x in range(1000):in_pipe.send(x)in_pipe.close()son_p.join()print 主进程也结束了为什么上面
当主进程创建Pipe的时候Pipe的两个Connections连接的都是主进程当主进程创建子进程后Connections被拷贝了一份此时一共有2主进程 2子进程 4 个Connections随后我们关闭主进程中的 out_connection 和子进程中的 in_connection 端口即可建立一条主进程通往子进程的管道了 4. 由于Pipe之间的通信时通过in_conn.send()、out_conn.recv() 这种方式进行通信的因此如果当某一方调用了 .recv() 函数但一直没有另外的端口使用 .send() 方法的话recv() 函数就会阻塞住。为了避免程序阻塞我们在明确另一个端口不会再调用 .send() 函数后可以直接将发送端口给 close()这样以来如果接收端还在继续调用 .recv() 方法的话程序就会抛出 EOFError 的异常
进程池 Pool
当需要创建的子进程数量不多时可以直接利用 multiprocessing 中的 Process 动态成生多个进程但如果是上百甚至上千个目标手动的去创建进程的工作量巨大此时就可以用到 multiprocessing 模块提供的 Pool 方法。
初始化 Pool 时可以指定一个最大进程数一般和CPU的核数相关一倍到两倍之间当有新的请求提交到 Pool 中时如果池还没有满那么就会创建一个新的进程用来执行该请求但如果池中的进程数已经达到指定的最大值那么该请求就会等待直到池中有进程结束才会用之前的进程来执行新的任务
from multiprocessing.pool import Pool
import os, time, randomdef worker(msg):t_start time.time()print(%s 开始执行,进程号为%d % (msg,os.getpid()))# random.random()随机生成 0~1 之间的浮点数time.sleep(random.random()*2)t_stop time.time()print(msg,执行完毕耗时%0.2f % (t_stop-t_start))if __name__ __main__:po Pool(3) # 定义一个进程池最大进程数 3for i in range(0,10):# Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))# 每次循环将会用空闲出来的子进程去调用目标po.apply_async(worker,(i,))print(----start----)po.close() # 关闭进程池关闭后 po 不再接收新的请求po.join() # 等待 po 中所有子进程执行完成必须放在 close 语句之后print(-----end-----)常用函数解析
常用函数说明apply_async(func[, args[, kwds]])使用非阻塞方式调用 func并行执行堵塞方式必须等待上一个进程退出才能执行下一个进程args 为传递给 func的参数列表kwds 为传递给 func 的关键字参数列表close()关闭 Pool使其不再接受新的任务terminate()不管任务是否完成立即终止join()主进程阻塞等待子进程的退出 必须在 close 或 terminate 之后使用
进程池中的Queue
如果要使用 Pool 创建进程就需要使用 multiprocessing.Manager()中的 Queue()而不是 multiprocessing.Queue
给一个使用进程池时进程间如何通信的例子
from multiprocessing import Manager,Pool
import os,time,randomdef reader(q):print(reader 启动(%s),父进程为(%s) % (os.getpid(), os.getppid()))for i in range(q.qsize()):print(reader 从 Queue 获取到消息%s % q.get(True))def writer(q):print(writer 启动(%s),父进程为(%s) % (os.getpid(), os.getppid()))for i in helloworld:q.put(i)if __name____main__:print((%s) start % os.getpid())q Manager().Queue() # 使用 Manager 中的 Queuepo Pool()po.apply_async(writer, (q,))time.sleep(1) # 先让上面的任务向 Queue 存入数据然后再让下面的任务开始从中取数据po.apply_async(reader, (q,))po.close()po.join()print((%s) End % os.getpid()示例文件夹 copy 器多进程
import multiprocessing
import os
import time
import randomdef copy_file(queue, file_name,source_folder_name, dest_folder_name):copy 文件到指定的路径f_read open(source_folder_name / file_name, rb)f_write open(dest_folder_name / file_name, wb)while True:time.sleep(random.random())content f_read.read(1024)if content:f_write.write(content)else:breakf_read.close()f_write.close()# 发送已经拷贝完毕的文件名字queue.put(file_name)def main():# 获取要复制的文件夹source_folder_name input(请输入要复制文件夹名字:)# 整理目标文件夹dest_folder_name source_folder_name [副本]# 创建目标文件夹try:os.mkdir(dest_folder_name)except:pass # 如果文件夹已经存在那么创建会失败# 获取这个文件夹中所有的普通文件名file_names os.listdir(source_folder_name)# 创建 Queuequeue multiprocessing.Manager().Queue()# 创建进程池pool multiprocessing.Pool(3)for file_name in file_names:# 向进程池中添加任务pool.apply_async(copy_file, args(queue, file_name, source_folder_name, dest_folder_name))# 主进程显示进度pool.close()all_file_num len(file_names)while True:file_name queue.get()if file_name in file_names:file_names.remove(file_name)copy_rate (all_file_num-len(file_names))*100/all_file_numprint(\r%.2f...(%s) % (copy_rate, file_name) *50, end)if copy_rate 100:breakprint()if __name__ __main__:main()