注册 登录
编程论坛 C语言论坛

系统调用的问题

ditg 发布于 2020-06-09 22:21, 3301 次点击
《操作系统》教材:“在输入输出操作中直接使用底层的系统调用会产生这样一个问题,即它们的效率可能非常低,原因如下:系统调用会降低计算机的执行性能。……”

问题:为什么说效率非常低?
12 回复
#2
ditg2020-06-09 22:29
库函数最终也得使用系统调用,相比之下,不应该是库函数效率更低吗?要说功能完备,库函数赢;要说执行特定功能,增加了一堆代码后怎么效率反而高呢?
#3
fulltimelink2020-06-09 22:43
因为降低了调用次数?
#4
ditg2020-06-09 22:50
反正书上有幅图,用户程序那儿画了根线意思是通过系统调用进入核心态执行,应该跟次数没关系吧

这门课有点蒙圈啊……
#5
fulltimelink2020-06-10 07:09
我是这么理解的,比如文件写入,因为库函数有了缓冲区所以不用每次都使用系统调用,所以少了调用次数。
下面这个是我从网上找到的:


现在我们看一下,在没有缓冲区的情况下,利用gcc编译程序并运行,从文件读入一个字符的过程:

   用户态程序调用 getc(FILE* stream)  --->  GNU C库 getc  ---->系统调用 -----> GNU C返回代码 ---->用户态getc返回 --->读入成功

   其中红色文字部分表示比较耗时,代价比较高。试想如果我们读入10000个字符,那么这样一个耗时操作就要执行1000次。

   所以,C中引入了缓冲区,缓冲区实际上是一块内存空间,这样当进行系统调用的时候,就不只读一个字符了,C标准库中stdio.h中定义了BUFSIZE就是缓冲区的大小,即每次读入数据的大小。这样结构就发生了变化:

  用户态程序调用 getc(FILE* stream)  --->  GNU C库 getc  ---->系统调用 ----->读入缓冲区----> GNU C返回代码 ---->用户态getc返回 --->读入成功

  遮样当时图读取第二个字符的时候,就免去了红色的部分,而是用缓冲区取代了原来的系统调用部分,大大减少了系统调用的次数。提高程序的效率。
#6
ditg2020-06-10 09:34
网上这个实在是不敢苟同……

read函数也在用户空间申请缓冲区(参数里就明确了),然后根据i节点文件类型再调用不同的读写函数,最后应该是利用类似put_fs_byte把获取的字节一个字节一个字节写进缓冲区,空间剩余部分填0。

getc参数FILE里有两项cha *__bufp和char *buf用于标识缓冲区,如果只在固定BUFSIZ=8192相当于2页连续空间里进行类似操作;那read函数就算再差,在缓冲区中申请4页连续空间应该还不难,实在分配不了就等着缓冲区解锁直到分配成功,再怎么说4页的效率也比getc的2页高吧
#7
fulltimelink2020-06-10 10:57
是不是应该同“类型”的比较, 比如:read 和fread对比      
#8
ditg2020-06-10 12:00
库函数里倒是有一大堆,这个get那个get的

刚查了一份有221个系统调用的,跟读操作相关只有三个,read、readv-读缓冲组、pread-随机读(后面两个基本可以不考虑),对应写操作也只有类似的三个
#9
ditg2020-06-10 12:36
程序代码:
#include <stdio.h>

void hello(void)
{
    printf("hello, world\n");
}

void main(void)
{
    __asm__("cli; call hello");
}


试了一下关中断
#10
fulltimelink2020-06-10 21:03
个人感觉还有各种连接池、pool应该也是同样的目的,提高复用以降低连接的次数
#11
ditg2020-06-10 21:36
哎,7.11四六级考试,够折腾一个月了……
#12
ditg2020-06-10 23:33
回复 10楼 fulltimelink
这些概念倒是有,但好像也没地方解释清楚

比如linux内核文件系统里有个buffer.c,前段时间查资料有的叫高速缓冲区、有的叫高速缓冲池,有的还整出缓冲区和缓冲池的区别等等。进程通过block read函数从哈希表查找使用后失效数据的处理方式仅是依据内存各功能区设计,谁又会无聊到把缓冲块用后清零?其它也差不多,前一个连接池后一个线程池的,有复用问题但概念众多,整得人都快裂了
#13
fulltimelink2020-06-11 18:08
回复 12楼 ditg
没了解过你说的这个...,我说的是  mysql、redis 或者自己实现的第三方“连接池”,节约的是网络IO开销
1