系统编程day2-系统调用
1.系统编程
1.1系统编程概述
在操作系统下进行的编程叫做系统编程。操作系统为用户提供了系统调用的接口,应用通过这个接口可以对各种硬件资源进行访问。
1.2操作系统概述
操作系统可以协助进行各种资源的管理。而且,还可以把各种不同的设备关联起来。
2.系统调用
2.1类unix操作系统的软件层次
一些application可以直接通过系统调用去调用内核,大部分的应用还是需要通过shell或者库函数去调用系统。
kernel:最接近硬件的软件层
system call:外围的应用想要通过内核申请硬件资源,必须经过system call
2.2系统调用
2.2.1什么是系统调用
Linux操作系统提供了两百到三百个系统调用函数。
系统调用是操作系统内核提供给用户程序(运行在用户态)的接口,用于请求内核执行特权操作或访问受保护的资源。它是用户程序与操作系统内核之间的桥梁。
2.2.2系统调用的功能
就是通过上层可以借助系统调用函数进行进程管理、内存管理等资源操作。
2.2.3用户态和内核态
用户态:不能进行系统资源访问。
内核态:可以已经系统资源访问。
可以把系统资源比作银行金库的钱,我们作为普通用户(用户态)不能直接去拿金库里的钱,但是银行管理员(内核态)可以通过合理合规的方式进行存取。
2.2.4库函数与系统调用的关系
并不是所有的库函数都能进行系统调用。eg:Max()
那什么库函数是系统调用函数呢?
就比如fopen函数,我们可以通过这个函数对硬盘进行访问。
FILE *fopen(const char *pathname, const char *mode);
库函数里面的fopen函数要想进行系统资源的申请与使用,需要调用系统调用函数:open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
2.2.5系统调用的返回值
系统调用的返回值:
如果调用成功:一般返回0
如果调用失败:会返回一个非0负数,一般是-1
3.1文件描述符
Linux下一切皆文件!我们可以使用系统调用中 I/O 的函数(I:input,输入;O:output,输出),对文件进行相应的操作( open()、close()、write() 、read() 等)。
打开现存文件或新建文件时,系统(内核)会返回一个文件描述符,文件描述符用来指定已打开的文件。这个文件描述符相当于这个已打开文件的标号,文件描述符是非负整数,是文件的标识,操作这个文件描述符相当于操作这个描述符所指定的文件。
任何一个程序都会默认打开三个文件,他们的文件描述符分别是:
我们可以通过让一个程序阻塞,去查看进程的进程号
比如:
#include<stdio.h>
int main()
{while(1);return 0;
}
图中使用的a.out就是Linux下编译成功后的可执行文件。
然后我们需要进入相应的文件夹中
cd /proc/进程号/fd 就可以查看到打开的文件
这就是一个进程默认打开的三个文件的文件描述符。
每一个进程在执行的时候,都会获得一个文件描述符的表格。在程序运行起来后打开其他文件时,系统会返回文件描述符表中最小可用的文件描述符,并将此文件描述符记录在表中。
3.2open函数
函数原型:
#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 类型,如果打开成功,返回该文件的文件描述符,是一个非负数。后续操作这个文件描述符,就等价于操作这个文件。
打开失败:返回-1,可以用perror查看错误信息
参数:
const char * pathname:文件路径以及名字
flags:打开文件的行为标志,必选项 O_RDONLY, O_WRONLY, O_RDWR
可选项:
mode取值
就说白了,你直接设置成0777,系统最后会变成0775,不给其他用户可写权限。
3.3close函数
函数原型:
#include <unistd.h>
int close(int fd);
返回值:如果关闭成功 返回0,否则返回-1
参数:
fd:打开的文件描述符
3.4write函数
函数原型:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
函数功能:将指定内存地址中的数据写入到 fd中
返回值:
写入数据时候
数据全部写入,返回值等于写入的字节数count
数据部分写入,返回值小于应该写入的字节数count
写入失败:
返回-1,而且可以用perror打印错误信息
参数:
fd 要写入的文件描述符
*buf 取数据的内存缓冲区
count :要写入的字节数
3.4read函数
函数原型
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
函数功能:从fd文件描述符中读取指定的count个字节到buf中
返回值:
读取数据成功时候:
读取数据与count一致,返回值为count
也可能小于count,因为读取成功的数据比count小
读取失败:
返回-1,可以用perror查看错误信息
参数:
fd:要读取的文件
*buff 读取数据到buff中
count 读取的字节数
3.6remove函数(库函数)
函数原型
#include <stdio.h>
int remove(const char *pathname);
函数返回值:
删除成功返回0
删除失败返回非0负数,一般是-1
参数:要删除的文件或目录的路径名