嵌入式学习DAY25 --- 进程线程开始学习,进程的基本概念以及创建退出_嵌入式需要学进程吗(2)

学习路线:

这个方向初期比较容易入门一些,掌握一些基本技术,拿起各种现成的工具就可以开黑了。不过,要想从脚本小子变成黑客大神,这个方向越往后,需要学习和掌握的东西就会越来越多以下是网络渗透需要学习的内容:
在这里插入图片描述

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

CPU调度算法:

公平调度策略:
是按照时间片轮转的方法来实现多任务调度

抢占式任务调度:
有优先级,优先级即高的可以抢占优先级低的进程的执行资源。

Linux下进程的分类:

1.交互式进程
2.批处理进程
3.实时进程

进程的地址空间:

Linux操作系统采用的是虚拟内存管理技术,使得每个进程都有独立的地址空间。该地址空间是大小为4G的线性虚拟空间,用户所看到和接触到的都是该虚拟地址。无法看到实际的物理内存地址。利用这种虚拟地址不但更安全(用户不能直接访问物理内存),而且用户程序可以使用比实际物理内存更大的地址空间。
4GB的进程地址空间会被分成两个部分——用户空间与内核空间。用户地址空间是0~3G(0xC0000000),内核地址空间占据3-4GB。用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址。只有用户进程使用系统调用(代表用户进程在内核态执行)时,才可以访问到内核空间。每当进程切换,用户空间就跟着变化;而内核空间是由内核负责用设,它并不会随着进程改变,是固定的。内核空间地址有自己对应的页表,用户进程各自有不同的页表。每个进程的用户空间都是完全独立、互不相干的。

Linux,进程开辟个数的上线:
为了与老版本兼容,short int pid,32768
可以修改上线:
修改这个文件:/proc/sys/kernel/pid_max

Linux下进程的状态:
如何查看Linux 进程状态:
ps:静态查看进程信息
ps -aux
ps -ajx (SID)
top:动态查看活跃的进程信息
pstree:显示进程的父子关系/打印进程树
kill:给指定进程发送信号,查看Linux提供的信号

ps命令的输出内容:
	PPID:父进程ID       				*
	PID:进程ID 							*
	PGID:进程组ID 						*
	SID:会话组ID(会话期ID) 				*
	TTY:终端							*
	STAT:进程状态						*
			进程状态,用下面的代码中的一个给出:
			D    不可中断     Uninterruptible sleep (usually IO)
			R    正在运行,或在队列中的进程
			S    处于休眠状态
			T    停止或被追踪
			Z    僵尸进程
			W    进入内存交换(从内核2.6开始无效)
			X    死掉的进程
			<    高优先级
			N    低优先级
			N    低优先级
			L    有些页被锁进内存
			s    包含子进程
			+    位于后台的进程组
			l    多线程,克隆线程

	UID:进程的用户ID
	TIME:进程使用的总CPU时间
	COMMAND:执行进程时的命令
	USER:进程所有者
	%CPU:进程自最近一次刷新以来所占用的CPU时间和总时间的百分比
	%MEM:进程使用内存的百分比
	VSZ:进程使用的虚拟内存大小,以K为单位
	RSS:驻留空间的大小。显示当前常驻内存的程序的K字节数
	START:进程的起始时间
	NI	进程的优先级值,较小的数字意味着占用较少的CPU时间
	PRI	进程优先级。
	WCHAN	进程等待的内核事件名

Linux进程状态:
	运行态
	停止态
	僵尸态
	死亡态
	阻塞态
		可中断的阻塞态
		不可中断的阻塞态

进程信息存在:/proc目录下

进程的创建
进程创建技术:
1.完美拷贝
几乎拷贝父进程的所有内容,除了父进程的PID,PCB信息
2.写时拷贝
开辟好进程基本管理信息后,共享父进程的数据和代码,只有
需要更改时,才拷贝
较为节省内存开销,所以用的较多
Linux 2.6版本之后,大多使用写时拷贝

fork:
	/*需要包含的头文件*/
	#include <unistd.h>
	/*
	 *函数名:fork
	 *函数功能:创建子进程
	 *函数参数:void
	 *函数返回值:pid_t
	 *		>0: 父进程,代表子进程的pid
	 *      ==0: 子进程
	 *      -1: fork失败
	 */
	pid_t fork(void);


vfork
clone
system:<在正式工作时,不建议使用,容易产生死锁>
	/*需要包含的头文件*/
	#include <stdlib.h>
	/*
	 *函数名:system
	 *函数功能:fork一个子进程,执行一条shell指令
	 *函数参数:const char *command:指令内容
	 *函数返回值:int:见manual
	 */
	int system(const char * command);
sleep():
	/*需要包含的头文件*/
	#include <unistd.h>
	/*
	 *函数名:sleep
	 *函数功能:让进程/线程睡眠指定的秒数
	 *函数参数:unsigned int seconds:指定睡眠的秒数
	 *函数返回值:unsigned int:成功返回sleep的时间,失败返回0			
	 */
	 unsigned int sleep(unsigned int seconds);
fork():
	1.创建一个子进程
	2.2.6以后用写时拷贝,之前用完美拷贝
	3.子进程和父进程执行顺序不确定
	4.有两个返回值,
		>0:为父进程,返回值代表子进程的pid
		==0:为子进程,返回值为0
vfork():
	1.创建子进程,阻塞父进程
	2.子进程先执行
	3.使用的是写时拷贝
	4.有两个返回值,
		>0:为父进程,返回值代表子进程的pid
		==0:为子进程,返回值为0

clone():
	不管是fork()还是vfork(),底层实现都是clone()
	该函数返回子进程的进程号,可以有选择性的拷贝
	父进程的内容。

system():
	fork() + execl()
	创建一个进程,并执行一个shell命令
	不建议执行耗时命令,容易产生死锁的情况

进程的执行

exec函数族:
一般用来执行程序,而不是程序员自己灵活编写的代码
要求执行的是可执行文件。
当判断是否为子进程时,直接写相应的代码
这种方式比较灵活
system
同execl,但容易发生死锁
exec x x:
l e
v p
第五位的选项:
l:命令行参数以枚举形式输入,包含命令本身,以NULL结尾
v:命令行参数以指针数组形式传入,即把list内容写入指针数组
第六位的选项:
e:在指定的位置中执行查找可执行文件
p:在系统环境变量中执行查找可执行文件

exec函数族只能执行指定的可执行文件,是一种不够灵活的执行特定任务
的方法,掌握 execve execlp就可以了

进程的销毁
exit:
	调用退出处理函数
	清理I/O缓冲区
_exit:
	没有上述操作	

获取进程表识:
#include <sys/types.h>
#include <unistd.h>

获取当前进程的pid
pid_t getpid(void);
获取父进程的pid
pid_t getppid(void);

标准IO缓冲区:
缓冲区的分类:
全缓冲:普通文件
行换成:stdin,stdout
无缓冲:stderr
ANSI C(C89)要求缓冲具有以下特点:
1.当且仅当标准输入和标准输出并不涉及交互设备时,它们才可以使用全缓冲。

这里并没有交代如果标准输入和标准输出涉及交互作用设备时,它们使用无缓冲还是行缓冲。

大多数系统默认使用下列类型的缓冲区:
1.标准错误是不带缓冲区的
2.如果涉及终端设备的流,则它们是行缓冲的
3.否则是全缓冲

注意:终端牵扯标准输入/输出流(stdin/stdout)

在我们使用的linux/ubuntu中:
全缓冲的大小为:4096 Byte
行缓冲的大小为:1024 Byte

如何验证全缓冲的大小:
原理:缓冲区存不下数据的时候,会刷新缓冲区(正常情况)
注意:为了避免进程退出刷新缓冲区,需要_exit()函数来做这件事情
或者使用while(1)还阻塞进程,防止进程退出(不建议使用,比较难理解)

例子:

#include <stdio.h>
		#include <unistd.h>

		int main()
		{
		        FILE \*fp = NULL;
		        fp = fopen("a.txt","r+");
		        if(NULL == fp)
		        {
		                puts("open file error.");
		                return -1;
		        }

		        int i = 0;
		        //当缓冲区中的数据<=4096,在没有其他强制刷新的情况下,不会
		        //清空缓冲区,只有当缓冲区中的数据>4096个字符时,才会刷新
		        for(i = 0; i < 4096; i++)
		        {
		                fputc('a',fp);
		        }
		        \_exit(0);
		}

	输出结果:执行之后,a.txt没有写入数据
		-rw-rw-r-- 1 farsight farsight    0 May  6 19:37 a.txt

	上面的实验结果说明:缓冲区没有满,数据没有写入,也证明了大小为4096

#include <stdio.h>
		#include <unistd.h>

		int main()
		{
		        FILE \*fp = NULL;
		        fp = fopen("a.txt","r+");
		        if(NULL == fp)
		        {
		                puts("open file error.");
		                return -1;
		        }

		        int i = 0;
		        //当缓冲区中的数据<=4096,在没有其他强制刷新的情况下,不会
		        //清空缓冲区,只有当缓冲区中的数据>4096个字符时,才会刷新
		        for(i = 0; i < 4200; i++)
		        {
		                fputc('a',fp);
		        }
		        \_exit(0);
		}

	输出结果:执行之后,a.txt写入数据,并且只写了缓冲大小个数据
    	-rw-rw-r-- 1 farsight farsight 4096 May  6 19:39 a.txt

如何验证行缓冲的大小:
原理:同全缓冲的原理

例子:

#include <stdio.h>
		#include <unistd.h>

		int main()
		{
				//当缓冲区中的数据<=1024,在没有其他强制刷新的情况下,不会
		        //清空缓冲区,只有当缓冲区中的数据>1024个字符时,才会刷新
		        int i = 0;
		        for(i = 0; i < 1024; i++)
		        {
		                fputc('a',stdout);
		        }
		        \_exit(0);
		}

	输出结果:
		没有数据输出

	#include <stdio.h>
	#include <unistd.h>

int main()
	{
			//当缓冲区中的数据<=1024,在没有其他强制刷新的情况下,不会
	        //清空缓冲区,只有当缓冲区中的数据>1024个字符时,才会刷新
	        int i = 0;
	        for(i = 0; i < 1030; i++)
	        {
	                fputc('a',stdout);
	        }
	        \_exit(0);
	}

	输出结果:写入1024个数据
		aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa		



### 给大家的福利


**零基础入门**


对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。


![](https://img-blog.csdnimg.cn/img_convert/95608e9062782d28f4f04f821405d99a.png)


同时每个成长路线对应的板块都有配套的视频提供:


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a91b9e8100834e9291cfcf1695d8cd42.png#pic_center)


因篇幅有限,仅展示部分资料

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/topics/618540462)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 21
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值