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


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

    ##教材学习总结 一.标准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应用程序开发标准教程》
  • 相关阅读:
    2009中国IT界名人
    jQuery简介
    Spring下载地址
    ContextLoaderListener
    MyBatisUtil类
    SSM事务
    后台管理中心跳转问题解决
    mybatis返回boolean值时数据库返回null
    yarn作业提交过程
    Hadoop集群运行wordcount jar包出错
  • 原文地址:https://www.cnblogs.com/qiaoye06/p/6882152.html
Copyright © 2020-2023  润新知