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

81 阅读6分钟
		进程状态,用下面的代码中的一个给出:
		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缓冲区:  
 缓冲区的分类:  
 全缓冲:普通文件  
 行换成:stdinstdout  
 无缓冲: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		

无缓冲:  
 stderr  
 例子:



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

int main()
{
        int i = 0;
        fputs("error 011",stderr);
        \_exit(0);
}


输出: farsight@ubuntu:~/ioclass./a.outerror011farsight@ubuntu: /ioclass ./a.out error 011farsight@ubuntu:~/ioclass


如果想用其他方法来强制刷新缓冲区,有以下几种方法:  
 1.使用函数fflush  
 2.行缓冲中遇到’\n’  
 3.exit(),进程退出时  
 4.程序自动退出时(即,原因是3,进程自动退出)  
 5.fclose()调用时  
 6.正常return 0


如果想程序退出,且不刷新缓冲区:  
 1.使用\_exit()函数


============================================================================================  
 如果想要设置缓冲区的大小:  
 使用setvbuf()函数来实现:  
 /\*  
 \*函数名:setvbuf  
 \*函数功能:设置缓冲区大小  
 \*函数参数:  
 \* FILE \*stream:被设置缓冲区的文件流指针  
 \* char \*buf:缓冲区的首地址  
 \* int mode:  
 \* \_IONBF unbuffered(无缓冲)  
 \* \_IOLBF line buffered(行缓冲)  
 \* \_IOFBF fully buffered(全缓冲)  
 \*  
 \* size\_t size:缓冲区的大小(stdio.h有一个BUFSIZ宏,是8192)  
 \*函数返回值:int,成功返回0,失败返回错误码  
 \*/  
 int setvbuf(FILE \*stream, char \*buf, int mode, size\_t size);


如何获取缓冲:  
 1.当文件上发生第一个IO操作时,才会调用malloc



例子:



#include <stdio.h> #include <string.h> int main() {

	        char bufr[8192] = {0};
	        printf("BUFSIZ:%d\n",BUFSIZ);
	        FILE \*fp = NULL;
	        fp = fopen("a.txt", "r+");
	        if(NULL == fp)
	        {
	                puts("open stdout error.");
	                return -1;
	        }
	        char buf[20];
	        memset(buf, 0, sizeof(buf));
	        //读操作之前打印
	        printf("bufsize:%d\n",fp->_IO_buf_end - fp->_IO_buf_base);
	        printf("readbufsize:%d\n",fp->_IO_read_end - fp->_IO_read_base);
	        printf("writebufsize:%d\n",fp->_IO_write_end - fp->_IO_write_base);
	        fread(buf, 1, sizeof(buf), fp);
	        puts(buf);
	        puts("=================");
	        printf("readbufsize:%d\n",fp->_IO_read_end - fp->_IO_read_base);
	        char str[] = "hellodlfjsdklffsdjflkdksfjlkdsfjlklkdksjfkl";
	        fwrite(buf, strlen(buf),1,fp);
	        //读写操作之后打印
	        printf("writebufsize:%d\n",fp->_IO_write_end - fp->_IO_write_base);
	        printf("bufsize:%d\n",fp->_IO_buf_end - fp->_IO_buf_base);
	        puts("&&&&&&&&&&&&&&&&&&&&&&&");
	        char \*p = NULL;
	        //通过setvbuf来重新设置缓冲区大小
	        setvbuf(fp,bufr,_IOFBF,BUFSIZ);
	        fseek(fp, 0L, SEEK\_SET);
	        memset(buf, 0, sizeof(buf));
	        printf("bufsize:%d\n",fp->_IO_buf_end - fp->_IO_buf_base);
	        printf("readbufsize:%d\n",fp->_IO_read_end - fp->_IO_read_base);
	        printf("writebufsize:%d\n",fp->_IO_write_end - fp->_IO_write_base);
	        fclose(fp);
	        return 0;
	}


代码输出:
	farsight@ubuntu:~/ioclass$ ./a.out 
	BUFSIZ:8192
	bufsize:0
	readbufsize:0
	writebufsize:0
	aaaaaaaaaaaaaaaaaaaa
	=================
	readbufsize:4096

img img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取