简单概念
- fd
#include <unistd.h>
#include <string.h>
int main(int argc,char* argv[])
{
char buf[20]={0};
read(0,buf,15);
write(1,buf,strlen(buf));
return 0;
}
- 如果想查看某个系统编程的接口,比如想查看 open 函数的用法,可以这样操作:man 2 open。可以看到open函数在哪里定义的,以及open函数的使用方法。
- 首先看一个简单的demo1
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char* argv[])
{
int fd=0;
fd=open("hello.txt",O_RDWR|O_CREAT,0666);
if(fd == -1)
{
printf("open file failed!\n");
return -1;
}
char string[128]="Hello Word!\n";
write(fd,string,strlen(string));
fsync(fd); //1.为什么要用fsync?因为调用write(...)函数时候,并没有真正写入到磁盘上,可能还在缓冲区中,等缓冲区满了之后,再一起写到磁盘中。
//2.所以,fsync(...) 是强制让缓冲区中的内容写到磁盘中。
char* buf=(char*)malloc(20);
memset(buf,0,20);
lseek(fd,0,SEEK_SET); // 1.SEEK_SET : 代表文件开始 SEEK_CUR:文件当前位置 SEEK_END:文件末尾
// 2.因为上面调用 write(...)函数,使得文件指针偏移了,现在使用lseek(...)将文件指针还原。
read(fd,buf,strlen(string));
printf("%s",buf);
free(buf);
close(fd);
return 0;
}
3.自己动手实现一个cp 命令
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFFERSIZE 4096
int main(int argc,char* argv[])
{
if(argc != 3)
{
printf("usage:\n copy src dst\n");
return 1;
}
int srcfd = open(argv[1],O_RDONLY);
if(srcfd == -1)
{
perror("open");
return 1;
}
int dstfd = open(argv[2],O_CREAT|O_WRONLY,0666);
if(dstfd == -1)
{
perror("open");
return 1;
}
int len=0;
char buffer[BUFFERSIZE] = {0};
while((len=read(srcfd,buffer,BUFFERSIZE)) > 0)
{
if(write(dstfd,buffer,len) != len)
{
perror("error");
return 2;
}
}
if(len<0)
{
perror("read error");
return 3;
}
close(srcfd);
close(dstfd);
return 0;
}
系统调用与C标准库函数
-
一般来说C语言中很多函数 fopen、fclose、fseek、fread、fwrite等待都是对Linux 系统调用的封装。
一般来说,Linux各种系统的调用流程如上图所示。 -
首先用户空间调用 read 函数,通过中断机制,进入到内核空间,内核空间有一个虚拟文件系统(VFS),虚拟文件系统(VFS)是对内核中各种各样的设备的抽象。
-
我们知道Linux中一切皆文件,对每个设备都抽象成一个文件。每个文件的 读/写 又是不一样的,因此需要一个公用的VFS虚拟文件系统对内核的文件进行抽象。
系统调用的基本流程:
- 软中断:X86下init0X80;ARM架构下SWI软中断指令
- 寄存器保存相关参数:参数、系统调用号
- 进入内核态,执行内核特权指令代码函数
- 返回值保存到寄存器
- 返回到用户态、系统调用结束