Linux - 系统调用与库函数

文件基本概念

文件

可被读写的对象

具备一定权属性,包括访问权限、类型等

文件系统

文件及其属性的集合,提供了命名及管理机制

文件结构

字节流,没有特定内部结构

文件类型

普通文件
目录
设备文件
字符文件/块文件
FIFO文件(如管道文件)
Socket文件
符号链接

硬连接

不同的文件名对应同一个inode

不能跨越文件系统

相应系统调用

link()

[root@localhost link]# ls -l
total 1
-rw-r--r--   1 root     root          667 Oct 15 13:39 a
[root@localhost link]# ln a b
[root@localhost link]# ls -l
total 2
-rw-r--r--   2 root     root          667 Oct 15 13:39 a
-rw-r--r--   2 root     root          667 Oct 15 13:39 b
[root@localhost link]# rm a
rm: remove `a‘? y
[[email protected] link]# ls -l
total 1
-rw-r--r--   1 root     root          667 Oct 15 13:39 b

符号链接

存储被链接文件的文件名(而不是inode)实现链接

可跨越文件系统

相应系统调用

symlink()

[root@localhost symlink]# ls -l
total 1
-rw-r--r--   1 root     root          667 Oct 15 13:39 a
[root@localhost symlink]# ln -s a b
[root@localhost symlink]# ls -l
total 1
-rw-r--r--   1 root     root          667 Oct 15 13:39 a
lrwxrwxrwx   1 root     root            1 Oct 15 14:20 b -> a
[root@localhost yy]# rm a
rm: remove `a‘? y
[[email protected] symlink]# ls -l
total 0
lrwxrwxrwx   1 root     root            1 Oct 15 14:20 b -> a
[[email protected] symlink]# cat b
cat: b: No such file or directory

文件系统类型

Windows文件系统
FAT16,FAT32,NTFS
传统UNIX:UFS (Unix File System)
BSD文件系统:FFS(Fast File System)
Proc文件系统:只存在于内存中
Linux文件系统
ext2(在Linux 2.0.x中首次使用)
reiserfs(在Linux 2.2.x中首次使用)
ext3(在Linux 2.4.x中首次使用)
xfs(源于SGI )
Jfs(源于IBM )
嵌入式小型文件系统
CRAMFS
JFFS2

虚拟化

只存在于内存中

组成

超级块

存储已安装文件系统的信息

通常对应磁盘文件系统的文件系统控制块

文件对象

inode对象

存储单个文件的信息

通常对应磁盘文件系统的文件控制块

dentry对象

描述文件名及相关联的inode信息

虚拟文件的目录项

dentry定义位置:include/linux/dcache.h

描述目录与文件的关系树

目录高速缓存(directory cache)

保存每一个曾被读取的目录/文件的dentry项

加快文件查找效率

虚拟文件系统各对象之间关系

inode对象与文件:一对一
dentry对象与inode对象:多对一(硬连接)
文件对象与dentry对象:多对一

EXT2文件系统

第一个磁盘块用于引导,其余部分被分成若干组
各组大小相同且顺序存放
可通过组序号确定组在磁盘上的位置
组的构成
文件系统超级块
所有组描述符
数据块位图
inode位图
inode表
数据块

EXT2文件系统体系结构

每组都有一份超级块和所有组描述信息的拷贝

正常情况下内核只使用第0组的信息

当组0的拷贝遭到损坏时便可根据其它组的拷贝恢复

数据块位图

大小为一个块

每一位顺序对应组中的一个块

0表示可用

1表示已用

inode表

存放文件及目录的inode数据

inode位图

表示对应的inode表空间是否已被占用

EXT3文件

日志文件系统(journaling file system)

利用数据库的日志技术(log, checkpoint)

3种日志方式

journal, ordered, writeback

日志记录在/.journal中(隐藏文件)

Kjournald—5s

proc文件系统

虚拟文件系统,只存在于内存中

可查询、设置系统的运行情况及各种系统参数

系统中的很多应用都依赖于proc文件系统

如命令lsmod等同于 cat /proc/modules

文件大小为0

很多文件名反映了内核的相应参数

可通过该文件名修改参数值

如#echo 2048 > /proc/sys/shmmni,修改共享内存段的限制

/proc下的“数字目录”指代相应pid的进程

如目录“1”下的内容就是1号进程的各种信息

系统调用与库函数的基本概念

均以C函数形式出现

系统调用

Linux内核的对外接口

用户程序与内核之间的唯一接口

提供最小接口

程序员手册第二节

库函数

依赖于系统调用

提供较复杂功能

例:标准I/O库

程序员手册第三节

无缓存I/O与有缓存I/O

无缓存I/O

读/写 ->设备

文件描述符

ANSI C不支持、POSIX支持

设备文件访问时使用

有缓存I/O

标准 I/O库提供

处理很多细节

缓存分配

以优化长度执行I/O

流 -> FILE指针

普通文件

基本I/O系统调用

文件描述符
基本I/O
open() / creat(), close(), read(), write(), lseek()
dup()/dup2()
fcntl()
ioctl()

文件描述符

非负整数

定义形式

int fd;

标准文件描述符定义(

STDIN_FILENO (0)
STDOUT_FILENO (1)
STDERR_FILENO (2)

文件操作的一般过程

打开-读/写-[定位]-关闭

/* a rudimentary example program */
#include <fcntl.h>

main()
{
    int fd, nread;
    char buf[1024];

    /*open file “data” for reading */
    fd = open(“data”, O_RDONLY);

    /* read in the data */
    nread = read(fd, buf, 1024);

    /* close the file */
    close(fd);
}

出错处理

UNIX风格
返回值
“errno” 变量(/usr/include/errno.h)
extern int errno;
strerror
#include <string.h>
char *strerror(int errnum);
返回出错的字符串描述
perror()
#include <stdio.h>
void perror(const char *msg);
打印错误原因字符串

open()/creat()系统调用

功能
打开或创建一个文件或设备
头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数原型
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
返回值
成功时返回新文件描述符
否则返回-1
功能
文件访问模式
取值说明(/usr/include/fcntl.h)
O_RDONLY:只读形式打开
O_WRONLY:只读形式打开
 O_RDWR:读写形式打开
O_APPEND:追加模式打开
O_TRUNC :若文件存在且为只读或只写成功打开,则将长度截为0
O_CREAT:若文件不存在则创建之
使用此选项时,需同时说明参数mode,说明文件的存取许可权位
O_EXCL:若同时指定O_CREAT,而文件已经存在,则出错
该参数可测试文件是否存在,如果不存在则创建此文件
creat()函数说明
等价于已参数O_CREAT|O_WRONLY|O_TRUNC执行open()

close()系统调用

功能
关闭文件描述符
头文件
#include <unistd.h>
函数原型
int close(int fd);
成功:返回0
失败:返回-1

read()/write()系统调用

read()
功能
从文件描述符读取数据
头文件
#include <unistd.h>
函数原型
ssize_t read(int fd, void *buf, size_t count);
返回值: 读到的字节数,若已到文件尾为0,若出错为-1
write()
功能
将数据写入文件描述符
头文件
#include <unistd.h>
函数原型
ssize_t write(int fd, const void *buf, size_t count);
返回值: 若成功为已写的字节数,若出错为-1

lseek()系统调用

功能
调节读写的偏移量
头文件
#include <sys/types.h>
#include <unistd.h>
函数原型
off_t lseek(int fildes, off_t offset, int whence);
返回值
成功时返回偏移量位置
否则返回-1
whence说明
SEEK_SET: 从文件头开始的偏移量
SEEK_CUR: 从当前位置开始加offset后的偏移值
SEEK_END: 从文件末开始加offset后的偏移值

dup()系统调用

功能
复制文件描述符
头文件
#include <unistd.h>
函数原型
int dup(int oldfd);
传给该函数一个现有描述符,返回一个新的描述符
新描述符是传给它的描述符的拷贝,即两描述符共享同一数据结构
如果对一个文件描述符执行lseek操作,得到的第一个文件的位置和第二个是一样的
返回值
成功时返回新文件描述符
否则-1
功能
复制文件描述符
头文件
#include <unistd.h>
函数原型
int dup2(int oldfd, int newfd);
允许规定一个有效描述符( oldfd )和目标描述符( newfd )
目标描述符将变成源描述符的复制品,即两个文件描述符指向同一文件,且是源描述符指向的文件
返回值
成功时返回新文件描述符
否则-1

fcntl()系统调用

功能
根据文件描述符来操作文件的特性
头文件
#include <unistd.h>
#include <fcntl.h>
函数原型
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
参数说明
fd:文件描述符
cmd:操作命令
arg:命令使用的参数
lock:同上
返回值
若成功,则依赖于cmd
若出错为-1
cmd参数说明
F_DUPFD:复制文件描述符
FD_CLOEXEC:设置close-on-exec标志
F_GETFD:读取文件描述符标志
F_SETFD:设置文件描述符标志
F_GETFL:读取文件状态标志
F_SETFL:设置文件状态标志
F_GETLK:获取记录锁
F_SETLK :释放记录锁
F_SETLKW:测试记录锁
时间: 2024-11-08 16:15:54

Linux - 系统调用与库函数的相关文章

Linux系统调用和库函数调用的区别

Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions).系统调用实际上就是指最底层的一个调用,在linux程序设计里面就是底层调用的意思.面向的是硬件.而库函数调用则面向的是应用开发的,相当于应用程序的api,采用这样的方式有很多种原因,第一:双缓冲技术的实现.第二,可移植性.第三,底层调用本身的一些性能方面的缺陷.第四:让api也可以有了级别和专门的工作面向. 1.系统调用 系统调用提供的函数如open, close, read,

linux平台学x86汇编(十七):在汇编中使用linux系统调用

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 在前面章节我们已经看到,启动系统调用需要使用INT指令.linux系统调用位于中断0x80,执行INT指令时,所有操作转移到内核中的系统调用处理程序,完成后执行转移到INT指令之后的下一条指令. linux的系统调用在如下文件(32位系统)可以查看: $ cat /usr/include/asm/unistd_32.h #ifndef _ASM_X86_UNISTD_32_H

Linux系统调用

系统调用概述 系统调用,顾名思义,说的是操作系统提供给用户程序调用的一组"特殊"接口.用户程序可以通过这组"特殊"接口来获得操作系统内核提供的服务,比如用户可以通过文件系统相关的调用请求系统打开文件.关闭文件或读写文件,可以通过时钟相关的系统调用获得系统时间或设置定时器等. 从逻辑上来说,系统调用可被看成是一个内核与用户空间程序交互的接口--它好比一个中间人,把用户进程的请求传达给内核,待内核把请求处理完毕后再将处理结果送回给用户空间. 系统服务之所以需要通过系统调

linux-man命令中的编号含义(包括系统调用和库函数讲解)

博文说明[前言]: 本文将通过个人口吻介绍linux的man命令中的编号含义(包括系统调用和库函数解释),在目前时间点[2017年6月13号]下,所掌握的技术水平有限,可能会存在不少知识理解不够深入或全面,望大家指出问题共同交流,在后续工作及学习中如发现本文内容与实际情况有所偏差,将会完善该博文内容. 本文参考文献引用链接: 1.http://www.cnblogs.com/chao1118/p/3715523.html2.http://blog.csdn.net/high_high/artic

[Linux]系统调用理解(1)

本文是Linux系统调用专栏系列文章的第一篇,对Linux系统调用的定义.基本原理.使用方法和注意事项大概作了一个介绍,以便读者对Linux系统调用建立一个大致的印象. 什么是系统调用? Linux内核中设置了一组用于实现各种系统功能的子程序,称为系统调用.用户可以通过系统调用命令在自己的应用程序中调用它们.从某种角度来看,系统调用和普通的函数调用非常相似.区别仅仅在于,系统调用由操作系统核心提供,运行于核心态:而普通的函数调用由函数库或用户自己提供,运行于用户态.二者在使用方式上也有相似之处,

ARM Linux系统调用的原理

转载自:http://blog.csdn.net/hongjiujing/article/details/6831192 ARM Linux系统调用的原理 操作系统为在用户态运行的进程与硬件设备进行交互提供了一组接口.在应用程序和硬件之间设置一个额外层具有很多优点.首先,这使得编程更加容易,把 用户从学习硬件设备的低级编程特性中解放出来.其次,这极大地提高了系统的安全性,因为内核在试图满足某个请求之前在接口级就可以检查这种请求的正确性. 最后,更重要的是这些接口使得程序具有可移植性,因为只要内核

Linux系统调用过程分析

參考: <Linux内核设计与实现> 0 摘要 linux的系统调用过程: 层次例如以下: 用户程序------>C库(即API):INT 0x80 ----->system_call------->系统调用服务例程-------->内核程序 先说明一下,我们常说的用户API事实上就是系统提供的C库. 系统调用是通过软中断指令 INT 0x80 实现的,而这条INT 0x80指令就被封装在C库的函数中. (软中断和我们常说的硬中断不同之处在于,软中断是由指令触发的,而不

Linux系统编程——Linux系统调用

系统调用概述 系统调用,顾名思义,说的是操作系统提供给用户程序调用的一组"特殊"接口.用户程序可以通过这组"特殊"接口来获得操作系统内核提供的服务,比如用户可以通过文件系统相关的调用请求系统打开文件.关闭文件或读写文件,可以通过时钟相关的系统调用获得系统时间或设置定时器等. 从逻辑上来说,系统调用可被看成是一个内核与用户空间程序交互的接口--它好比一个中间人,把用户进程的请求传达给内核,待内核把请求处理完毕后再将处理结果送回给用户空间. 系统服务之所以需要通过系统调

Linux系统调用及其效率

操作系统相关概念: 操作系统---管理计算机硬件与软件资源的软件,是用户与系统操作交互的接口,为在它上面运行的程序提供服务. 操作系统内核 ----操作系统的核心.负责管理系统的进程.内核.设备驱动程序.文件和网络系统,一套内核不是一套完整的操作系统,如Linux. Linux操作系统---基于Linux内核的操作系统,通常由Linux内核.Shell.文件系统和应用程序.常见的有RetHat .Fedora .Centos .Ubuntu和Andriod. Linux的运行空间: Linux的