《嵌入式程序设计》第五周学习总结

《嵌入式程序设计》第五周学习总结

##教材学习总结 一.标准I/O编程 标准I/O提供流缓冲的目的是尽可能减少使用read()和write()等系统调用的数量。 二.标准I/O3种类型的缓冲存储 (1)全缓冲:在这种情况下,当填满标准 I/O 缓存后才进行实际I/O 操作。存放在磁盘上的文件通常是由标准I/O 库实施全缓冲的。在一个流上执行第一次I/O 操作时,通常调用malloc()就是使用全缓冲。 (2)行缓冲:在这种情况下,当在输入和输出中遇到行结束符时,标准 I/O 库执行I/O 操作。这允许我们一次输出一个字符(如fputc()函数),但只有写了一行之后才进行实际I/O操作。标准输入和标准输出就是使用行缓冲的典型例子 (3)不带缓冲:标准 I/O 库不对字符进行缓冲。如果用标准I/O 函数写若干字符到不带缓冲的流中,则相当于用系统调用write()函数将这些字符全写到被打开的文件上。标准出错stderr通常是不带缓存的,这就使得出错信息可以尽快显示出来,而不管它们是否含有一个行结束符。 三.基本操作 (1)打开文件 ①函数说明 打开文件有三个标准函数,分别为:fopen(),fdopen()和freopen()。它们可以以不同的模式打开。但都返回一个指向FILE的指针,该指针指向对应的I/O流。此后,对文件的读写都是通过这个FILE指针来进行。其中fopen()可以指定打开文件的路径和模式。 ②函数格式定义 所需头文件:```#include``` 函数原型:```FILE *fopen(const char *path,const char *mode)``` 函数传入值:Path:包含要打开的文件路径及文件名 mode:文件打开状态 函数返回值:成功:指向FILE的指针 失败:NULL (2)关闭文件 ①函数说明 关闭标准流文件的函数为fclose(),该函数将缓冲区内的数据全部写入到文件中,并释放系统所提供的文件资源。 ②函数格式说明 所需头文件:```#include``` 函数原型:```int fclose(FILE *stream)``` 函数传入值:stream:已打开的文件指针 函数返回值:成功:0 失败:EOF (3)读文件 ①fread()函数说明 在文件流被打开之后,可对文件流进行读写等操作,其中读操作的函数为fread()。 ②fread()函数格式 所需头文件:```#include``` 函数原型:```size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream)``` 函数传入值:ptr:存放读入记录的缓冲区 size:读取的记录大小 nmemb:读取的记录数 stream:要读取的文件流 函数返回值:成功:返回实际读取到的nmemb数目 失败:EOF (4)写文件 ①fwrite()函数说明 fwrite()函数用于对指定的文件流进行写操作。 ②fwrite()函数格式 所需头文件:```#include``` 函数原型:```size_t fwrite(const void*ptr,size_t size,size_t nmemb,FILE* stream)``` 函数传入值:ptr:存放写入记录的缓冲区 size:写入的记录大小 nmemb:写入的记录数 stream:要写入的文件流 函数返回值:成功:返回实际写入的记录数目 失败:EOF 四.Linux中的进程包含三个段 (1)“数据段”:存放的是全局变量、常数以及动态数据分配的数据空间,根据存放的数据,数据段又可以分成普通数据段(包括可读可写/只读数据段,存放静态初始化的全局变量或常量)、BSS数据段(存放未初始化的全局变量)以及堆(存放动态分配的数据) (2)“代码段”:存放的是程序代码的数据。 (3)“堆栈段”:存放的是子程序的返回地址、子程序的参数以及程序的局部变量等。 五.Linux下的进程管理 (1)启动进程 Linux下启动一个进程有两种进程:手工启动和调度启动。手工启动是由用户输入命令直接启动进程,而调度启动是指系统根据用户的设置自行启动进程 (2)调度进程 调度进程包括对进程的中断操作、改变优先级、查看进程状态等,在Linux下可以使用相关的系统命令实现其操作。 ①Linux中进程调度常见命令 ps:查看系统中的进程 top:动态显示系统中的进程 nice:按用户指定的优先级运行 renice:改变正在运行进程的优先级 kill:向进程发送信号(包括后台进程) crontab:用于安装、删除或者列出用于驱动cron后台进程的任务 bg:将挂起的进程放到后台执行 ##课堂学习延伸 一.进程的定义: 进程是具有独立功能的程序在某个数据集上的执行过程,是系统进行资源分配和调度的一个独立单位。这里,程序指一组操作序列,而数据集则是接受程序规定操作的一组存储单元的内容。 二.进程的特征: ① 动态性:它由创建而产生,由调度而执行,由撤消而消亡。 ② 独立性:进程是CPU调度的一个独立单位。 ③ 并发性:任何进程都可以同其它进程一起向前推进。 ④ 异步性:每个进程都与其相对独立的不可预知的速度向前推进。  ⑤ 结构特征:进程的组成:程序+数据+PCB 。 三.进程和程序的区别 ① 进程是程序的执行,动态性。 ② 进程是程序的一次执行过程,生命周期。 ③ 进程是有结构的,PCB。 ④ 进程与程序并非一一对应,一个进程可以涉及到一个成几个程序的执行;反之,同一程序可以对应一个成多个进程,即同一程序段可以在不同数据集合上运行,可构成不同的进程。 ![](http://images2015.cnblogs.com/blog/1150838/201705/1150838-20170521211617369-777109653.png) 四.进程的三种基本状态 (1)执行态(Running)。进程已获得处理机,其程序正在执行,单处理机中只有一个进程在执行,多处理机则有多个进程处于执行状态。

(2)就绪态(Ready)。当进程已分配到除处理机以外所有必要的资源时,它将处于准备执行状态,一旦获CPU,便立即执行。在一个系统中,可以有多个进程同时处于就绪状态。按时间片的大小,可构成多个就绪队列。

(3)阻塞态(Blocked)。一个进程正等待输入输出或等待某一事件发生而暂时停止执行,即使把处理机分配给该进程也无法执行。称此刻进程所处的状态为阻塞状态(等待状态)。引起进程阻塞的事件有多种,例如,请求I/O,申请缓冲区,等待某个信号或消息,系统中同时处于阻塞状态的进程可以有多个,根据阻塞的原因(比如,阻塞到哪个资源信号量上),可分成多个阻塞队列。

五.引起创建进程的事件:
1.用户登录:
为终端用户建立一进程
2.作业调度:(不是进程调度)
为被调度的作业建立进程
3.提供服务:
如要打印时建立打印进程
4.应用请求:
由应用程序建立多个进程
六.进程创建的方式
① 由系统模块统一创建。例如,在批处理系统中,由操作系统的作业调度程序为用户创建,相应的进程以完成用户作业的要求功能。
② 由父进程创建。例如,在层次结构的系统中,父进程创建子进程以完成并行工作。子进程还可以创建新的子进程,从而整个系统可以形成一个树型结构的家族。
七.进程创建原语
其步骤如下:
① 从系统的PCB表中找出一个空闲的PCB,并指定唯一的标识符PID。
② 为新进程分配资源,包括必要的内存空间、存放程序和数据的工作区等。
③ 根据调用者提供的参数,将新进程PCB初始化。这些参数包括新的进程名、进程优先级、进程状态等。
④ 将新进程加到就绪队列中。
八.进程创建图示

课后作业总结

一.fork()函数
1.fork()函数说明
fork()函数用于从已存在的进程中创建一个新进程,新进程称为子进程,而原进程称为父进程。
使用fork()函数得到的子进程是父进程的一个复制品,从父进程处继承了整个进程的地址空间,而子进程所独有的只有它的进程号、资源使用和计时器等,使用fork()函数,执行速度不是很快。
2.fork()函数语法
①所需头文件

#include<sys/types.h> // 提供类型 pid_t的定义
#include<unistd.h>

②函数原型

pid_t fork(void)

③函数返回值
0:子进程
子进程ID(大于0的整数):父进程
-1:出错
3.函数使用注意点
fork()函数使用一次就创建一个进程,所以若把fork()函数放在了if else判断语句中则要小心,不能多次使用fork()函数

二.exec()函数
1.exec函数族说明
exec函数族就提供了一个在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新的进程替换了。
2.exec函数族语法
①所需头文件

#include<unistd.h>

②函数原型

int  execl(const  char *path, const char *arg,...)
int  execv(const  char *path, char *const argv[])
int  execle(const char *path, const char *arg,..., char *const envp[])
int  execve(const char *path, char *const argv[], char *const envp[])
int  execlp(const  char *file, const char *arg,...)
int  execvp(const char *file, char *const argv[])

③函数返回值
-1:出错
3.exec函数族使用注意点。
在使用exec函数族时,一定要加上错误判断语句。exec很容易执行失败,其中最常见的有
①找不到文件或路径,此时errno被设置为ENOENT;
②数组argv和envp忘记用NULL结束,此时errno被设置为EFAULT;
③没有对应可执行文件的运行权限,此时errno被设置为EACCES;
三.exit()和_exit()函数
1.exit()和_exit()函数说明
exit()和_exit()函数都是用来终止进程的。当程序执行到exit()或_exit()时,进程会无条件地停止剩下的所有操作,清除包括PCB在内的各种数据结构,并终止本进程的运行。
_exit()函数的作用是:直接使进程停止运行,清除其使用的内存空间,并清除其在内核中的各种数据结构:
exit()函数则在这些基础上做了一些包装,在执行退出之前加了若干道工序。
2.exit()和_exit()区别
exit()函数在调用exit系统之前要检查文件的打开情况,把文件缓冲区中的内容写回文件。
3.exit()和_exit()函数族语法
①所需头文件

exit:#include<stdib.h>
_exit:#include<unistd.h>

②函数原型

exit:void exit(int status)
_exit:void _exit(int status)

③函数传入值
status是一个整形的参数,可以利用这个参数传递进程结束时的状态。一般来说,0表示正常结束;其他的数值表示出现了错误,进程非正常结束。
在实际编程时,可以用wait()系统调用接受子进程的返回值,从而针对不同的情况进行不同的处理
四.wait()和waitpid()函数
1.wait()和waitpid()函数说明

wait()函数是用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或者该进程接到了一个指定的信号为止。如果该父进程没有子进程或者他的子进程已经结束,则wait()就会立即返回。
waitpid()作用和wait()一样,但它并不一定要等待第一个终止的子进程,它还有若干选项,如可提供一个非阻塞版本的wait()功能,也能支持作业控制

2.wait()函数族语法

①所需头文件

#include<sys/types.h>
#include<sys/wait.h>

②函数原型

pid_t wait (int *status)

③函数传入值
这里的status是一个整形指针,是该子进程退出时的状态,status若不为空,则通过它可以获得子进程的结束状态。另外,子进程的结束状态可由Linux中一些特定的宏来测定

④函数返回值
成功:已结束运行的子进程的进程号
失败:-1

3.waitpid()函数语法

①所需头文件

#include<sys/types.h>
#include<sys/wait.h>

②函数原型

pid_t waitpid (pid_t  pid , int *status , int options)

③函数传入值

Pid :
pid>0:只等待进程ID等于pid的子进程,不管已经有其他子进程运行结束退出了,只要指定的子进程还没有结束, waitpid()就会一直等下去
pid=-1:等待任何一个子进程退出,此时和wait()作用一样
pid=0:等待其组ID等于调用进程的组ID的任一子进程
pid<-1:等待其组ID等于pid的绝对值的任一子进程

status:
这里的status是一个整形指针,是该子进程退出时的状态,status若不为空,则通过它可以获得子进程的结束状态。另外,子进程的结束状态可由Linux中一些特定的宏来测定

options:
WNOHANG:若由pid指定的子进程不立即可用,则waitpid()不阻塞,此时返回值为0

WUNTRACED:若实现某支持作业控制,则由pid指定的任一子进程状态已暂停,且其状态自暂停以来还未报告过,则返回其状态

0:
同wait(),阻塞父进程,等待子进程退出

④函数返回值

正常:已经结束运行的子进程的进程号
使用选项WNOHANG且没有子进程退出:0
调用出错:-1

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 15 20/20
第一周 200/200 2/2 1/1 vi的使用
第二周 1000/1200 3/7 7/8 gcc,gdb,makefile
第三周 500/1700 1/8 4/12 U-Boot
第四周 1500/3200 1/9 6/18 Linux的内核
第五周 1200/4400 1/10 3/21 标准I/O的编程,linux下进程相关的基本系统调用

参考资料

  • 《嵌入式Linux应用程序开发标准教程》
posted @ 2017-05-20 14:56  黑麦威士忌  阅读(195)  评论(0编辑  收藏  举报