系统调用与库函数关系|学习笔记 您所在的位置:网站首页 库函数和系统调用 系统调用与库函数关系|学习笔记

系统调用与库函数关系|学习笔记

#系统调用与库函数关系|学习笔记| 来源: 网络整理| 查看: 265

开发者学堂课程【物联网开发- Linux 高级程序设计全套视频:系统调用与库函数关系】学习笔记,与课程紧密联系,让用户快速学习知识。 

课程地址:https://developer.aliyun.com/learning/course/660/detail/10980

系统调用与库函数关系

 

内容简介:

一、库函数的函数类型

二、系统调用与库函数的关系

三、Printf函数执行过程

四、小结

 

一、库函数的函数类型

1、无需系统调用的

接下来讲系统调用和库函数的关系,首先讲一下库函数,库函数是由两类函数构成的:一类库函数不需要系统调用、另一类库函数需要系统调用,先看第一类库函数,它不需要切换到内核空间即可完成函数的全部功能,并且将结果返回给应用程序,比如 strcpy 、 bzero这些函数,例

如 strcpy 代码如下:

​char * strcpy(char *dest,const char *src)​

​{​

​char *p=dest;​

​while(*src != ‘\0’)​

​{​

​*dest = *src;​

​src++;​

​dest ++;​

​}​

​*dest = ‘\0’;​

​return p;​

​}​

看整个 strcpy 函数它是否系统调用内核函数?

没有,在应用程序这一层就已经把它的功能实现了,这就是 strcpy 的源码,这类函数是不需要系统调用的。

2、需要系统调用

但是有一类函数需要系统调用,需要切换到内核空间,这类函数通常通过封装系统调用去实现相应功能,比如 printf 或者 fread ,注意在 C 语言当中,库函数讲 fread 时,在 fread 函数的源码中,它肯定要去调 read ,它在去调 read 时通过 read 进入内核,因为read 函数是系统调用,应用程序只能通过系统调用进入内核,所以像 fread 的函数,它就需要系统调用,这是第二类库函数需要调系统调用的。

 

二、系统调用与库函数的关系

1、关系图展示

接下来看一张图,即库函数和系统调用的关系,并不是所有的系统调用都被封装成了库函数,系统提供的很多功能都必须通过系统调用才能实现,

看图如下所示:

image.gif

2、关系图解析

平常点击应用程序,在应用程序当中经常是调库函数,而库函数是分为两类,即需要系统调用的和不需要系统调用的,像 strcpy ,应用程序调 strcpy 是直接在 C 库里面建了;

还有一类在应用程序当中,比如 fread , fread 去调库函数,再去调 read 、调系统调用,然后通过系统调用接口,进入内核,通过内核再去往硬盘上的文件中写入数据,它是一个过程;

还有一种是在应用程序当中可以直接系统调用,调 read 直接将数据写到文件里面去。

在此要注意, read 可以调 fread ,即间接的调 read ,像有些函数即创建多进程的函数就不在库函数当中,它就只能通过系统调用进入内核,在内核当中创建多任务,这就是库函数跟系统调用的关系,库函数有的不需要系统调用,有的需要系统调用,像 strcpy 是在用户态就可以实现功能,像fread 必须要用户态切到内核态才能实现功能。

3、频繁系统调用的影响

系统调用是需要时间的,程序当中频繁地使用系统调用会降低程序的运行效率,这是什么意思?

正常情况下应用程序是运行用户态,如果系统调用它是要切换到内核态的,注意如果切换到内核态,它要保存用户态的环境,然后调完了之后又返回到系统调用函数,然后再返回到用户态时再恢复环境,所以由用户态切换到内核态,且系统调用调完了之后、运行完内核函数之后,再返回到用户态时,其中状态的切换是需要消耗资源的,即保存环境恢复环境,所以如果频繁的进出内核,就会降低程序的运行效率。

4、用户态和内核态的区分原因

为什么分用户态和内核态?是为了保护操作系统内核,在电脑或手机上运行一个程序之后,经常那个应用程序会死机,但它并不会导致手机或电脑重启,操作系统不会崩掉,应用程序崩了就将应用程序杀死,然后操作系统不会崩,这样它便将程序运行状态分为用户态和内核态,正常情况下是不允许进入内核态的,除非通过系统调用进去,这样就有力地保护了内核,使操作系统更加稳定,然后注意频繁进出内核会降低程序的运行效率,因为会有环境的切换。

5、缓冲区的概念

在讲 fread 、 printf 、 C 语言时讲过缓冲区的概念,其实缓冲区相当于一块内存,像在程序的内存当中有一个数组 str ,要想把它写到文件里面打到屏幕上,首先库函数会将此数据先放到缓冲区里,最终它会刷到文件里边,即普通文件或者设备软件里面去,那么为什么要有缓冲区?是为了减少进出内核的次数,先将东西积累在缓冲区里边,然后积累到一定程度之后或当满足某种条件的时候,进出内核一次就可以搞定,相当于给你一个苹果,你跑一趟办公室,再给你一个苹果,你再跑一趟办公室,这样是没有效率的,给你一个苹果,你放到篮子里,给一个苹果就放在篮子里,当满足某种条件时,你提着篮子将许多个苹果一次送到办公室,这种效率会高一些,

请参考下图:

image.gif

 

三、printf 函数执行过程

在 printf 函数执行的过程,在应用程序当中去调 printf ,那么 C库当中它会将数据写到缓冲区里,最终它会调 write ,然后调系统调用,将缓冲区里的数据写到文件里面去,即标准输出设备文件里面,然后便到了屏幕上,这是一个程序执行的过程,

如下图所示:

image.gif

 

四、小结

上述的第一张图中清晰的讲了库函数跟系统调用内核函数之间的关系、用户态和内核态的两种状态、保护内核态用的频繁切换会降低程序运行效率,所以说就有缓冲区的概念,这是系统调用和库函数,库函是 C 库提供的,系统调用是内核提供,系统调用就是是内核提供的接口函数,在整个系统编程阶段就学各种各样的系统调用,学各种各样的内核提供的函数,能看明白和会调用,便能够实现相应的功能。

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有