1、概述
- 系统编程:指在操作系统下使用系统调用和库函数对资源进行管理
- 系统调用:操作系统提供给用户程序的一组“特殊的”函数接口
- 库函数:用户通过应用层库函数的接口,比如
fread()
对内核的系统调用进行操作 - 库函数和系统调用的关系:用户使用系统调用时,系统需要转换状态(即用户态和内核态),而这种转换会拉低程序的效率,所以库函数会根据需要设置缓冲区,减少系统调用的次数(即减少系统状态转换的次数),从而提高效率。大多数库函数的本质也是系统调用
除以上两种之外还可以通过shell编程,利用shell解释器操作内核的系统调用
系统调用可以按功能分为以下几种:进程控制、进程间通信、文件系统控制、系统控制、内存管理、网络管理、socket控 制、用户管理。
2、文件操作的系统调用
任何语言都躲不过对文件的操作,所以我们此处先说文件操作。
2.1 文件描述符
- 概述
- 系统调用中的I/O函数都是针对文件描述符
- 文件描述符是非负整数。打开现存文件或新建文件时,系统(内核)会返回一个文件描述 符。文件描述符用来指定已打开的文件。在系统调用(文件IO)中,文件描述符对文件起到标识作用,如果要操作文件,要通过文件描述符来操作
- 当一个程序运行或者一个进程开启时,系统会自动创建三个文件描述符 ,他们都有对应的宏、文件指针
0标准输入 STDIN_FILENO、stdin
1 标准输出 STDOUT_FILENO、stdout
2 标准输出出错 STDERR_FILENO、stderr
一个程序运行的时候最多可以创建2014个文件描述符,0~1023
文件描述符按照从小到大的顺序依次创建 ,如果中途有文件描述符被关闭了,则再创建的 文件描述符会先补齐之前的,然后依次递增创建 ,注意:不要认为最后创建的文件描述符一定是最大的
2.2 open( )函数
- 函数原型
#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);
//(文件不存在时)
- 功能:打开或者创建一个文件,返回文件描述符
参数:
pathname:指定路径的文件名,不指定路径默认为当前路径
flags:标志位,表明文件的打开方式
mode:文件权限位,当指定flags中有O_CREAT时,必须有这个参数, 如果没有O_CREAT,则不需要这个参数
返回值:
成功:文件描述符
失败:‐1
flags 的取值:
O_RDONLY:只读方式打开
O_WRONLY:只写方式打开
O_RDWR:可读可写方式打开
用位逻辑或 | 连接多个mode
O_CREAT:文件不存在则创建,使用时需要指定mode权限
O_EXCL:如果同时指定了O_CREAT,且文件已存在,则出错
O_TRUNC:如果文件存在,则清空文件内容
O_APPEND:写文件时,添加到末尾
O_NONBLOCK:当打开的文件是FIFO、字符文件、块文件时此选项为文件标识
mode 的取值:
只有在O_CREAT时使用mode,此参数用于控制权限
使用用八进制数表示,就是属主、属组、其他三类用户权限的124方法表示(1:可读、2:可写、4:可执行)
| 例如,00700表示属主有读、写、执行,属组和其他人没有权限
- 错误信息的输出使用全局变量errno
#include <errno.h>
errno是一个全局变量,当函数调用失败后,可以通过errno获取错误码
通过一个函数 perror
#include <stdio.h>
void perror(const char *s);
功能:输出函数调用失败的错误信息
参数:
s:打印错误信息的提示消息
返回值:无
- 案例
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main (int aygc ,char const* aygv [])
{
int fd;
fd = open("file.txt",O_RDONLY);
//使用open函数以只读方式打开文件file.txt
//使用fd保存获得的文件描述符
if(fd == -1)
//此处用来在打开失败时返回错误信息
{
//使用全局变量errno打印错误码
printf("errno = %d",errno);
//使用perror()输出调用失败
perror("fail to open");
return -1;
}
printf("fd =%d ",fd);
return 0;
}
2.3 close()函数
- 函数原型
#include <unistd.h>
int close(int fd);
- 功能:关闭一个文件描述符
- 参数:
fd:指定文件的文件描述符open函数的返回值 - 返回值:
成功:0
失败:‐1 - 案例
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main (int aygc ,char const* aygv [])
{
int fd;
fd = open("file.txt",O_RDONLY);
if(fd == -1)
//此处用来在打开失败时返回错误信息
{
//使用全局变量errno打印错误码
printf("errno = %d",errno);
//使用perror()输出调用失败
perror("fail to open");
return -1;
}
printf("fd =%d ",fd);
//当不在进行任何操作时,使用close()关闭文件描述符
//一旦关闭文件描述符,该文件描述符失效,即此后该文件描述符不能操作该文件
return 0;
}
2.4 write()函数
- 函数原型
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
- 功能:向文件写入数据
- 参数:
fd:指定的文件描述符
buf:要写入的数据
count:要写入的数据的长度 - 返回值:
成功:实际写入的字节数
失败:‐1 - 案例:向终端写入数据
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main (int argc, char const* argv[])
{
//使用标准输出的文件描述符(1)向终端写入数据
if(write(1,"hello word\n",12)==1)
{//若写入失败输出报错
perror("fail to write");
return -1;
}
return 0;
}
- 案例:向文件写入数据
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main (int argc, char const* argv[])
{
int fd;
fd = open("file.txt",O_WRONLY|O_CREAT|O_TRUNC,0664);
//因为不确定文件是否存在,所以参数中使用O_CREAT选项,若文件不存在则创建
if (fd == -1){perror("fail to open");return -1;}
ssize_t bytes;//接受write()返回值
//使用write()写入
if ((bytes=write(fd,"hello word\n",7))==-1)
{perror("fail to write");return -1}
//显示写入成功的位数
printf("bytes=%d",bytes);
close(fd);
return 0;
}
2.5 read()函数
- 函数原型
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
- 功能:从文件中读取数据
- 参数:
fd:指定的文件描述符
buf:保存读取到的数据
count:最大一次读取多少个字节 - 返回值:
成功:实际读取的字节数
失败:‐1
注意:如果读取到文件末尾,返回0 - 案例:从终端读取数据
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main (int argc, char const* argv[])
{
//使用标准输入的文件描述符(0)从终端读取数据
//若你在屏幕上输入的字符数大于第三个参数,则只会读取第三个参数设定个数个字符
//若你在屏幕上输入的字符数小于第三个参数,则要注意回车表示的换行符也会被读取
ssize_t bytes;
char str[32] = "";
if((bytes = read(0,str,6))==-1)
{perror("fail to read"); return -1;}
printf("bytes=%d",bytes);
printf("str=[%s]",str);
return 0;
}
- 案例:从文件中读取数据
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define N 64
int main (int argc, char const* argv[])
{
int fd;
fd = open("file.txt",O_WRONLY|O_CREAT|O_TRUNC,0664);
//因为不确定文件是否存在,所以参数中使用O_CREAT选项,若文件不存在则创建
if (fd == -1){perror("fail to open");return -1;}
ssize_t bytes;
char buf[N]="";
//使用read()从文件中读取
if((bytes=read(fd,buf,32))==-1)
{perror("fail to read");return -1;
}
printf("bytes=%d",bytes);
printf("buf=[%s]",buf);
//如果想一次性读完全部内容,可以使用循环,以read()的返回值作为判断条件(全部读完再读时返回值为0)
close(fd);
return 0;
}
2.6 remove()函数
- 函数原型
#include <stdio.h>
int remove(const char *pathname);
- 功能:删除指定文件
- 参数:
pathname:包含路径的文件名 - 返回值:
成功返回0。
失败返回‐1 - 案例
#include<stdio.h>
int main (int argc,char const* argv[])
{
if(remove("./file.txt")==-1)
{perroe("fail to remove");
return -1;
}
printf("delete done");
return 0;
未完待续…