文章目录
本片博客会粘贴部分代码,想要了解更多代码信息,可访问 小编的GitHub关于本篇的代码
理解更多文件系统知识: Linux文件系统----软连接和硬链接
C库的IO操作和系统调用的关系
C库IO操作函数:对系统调用的封装,C库IO操作函数调用系统调用接口实现。
C库函数是对系统调用的一层封装
文件流指针结构体包含了一个成员就是我们所说的文件描述符
FILE结构体:这个结构体中其实有一个成员是文件描述符,这个结构体中还有一个用户态的缓冲区。
文件流指针中还定义了一个缓冲区,,我们所说的换行刷新缓冲区(只针对于标准输出),实际就是刷新的这个缓冲区,这个缓冲区用于将短小数据组织合成大数据一次性写入文件,这样提高效率,而系统调用没有缓冲区。缓冲区就在FILE*这个结构体里,而系统调用则没有这个缓冲区。
系统调用函数
open
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
- flags:标志选项:
- 必选项:(这三个选项冲突,只能选择其中一个)
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写 - 非必选项:
O_CREAT 若文件存在则打开,不存在则创建
O_EXCL 与O_CREAT同时使用,若文件已经存在则报错返回
O_TRUNC 若文件存在则截断位0
O_APPEND 追加 - mode: 若文件不存在需要创建,用于指定创建的文件权限
- 返回值:
成功:非负整数(文件描述符),后续操作通过描述符完成
失败:-1
创建并打开文件file:
#include<fcntl.h>
#include<stdio.h>
#include<unistd.h>
int main()
{
umask(0);
int
open("./file",O_RDWR|O_CREAT,0664);
return 0;
}
write
ssize_t write(int fd, const void *buf, size_t count);
- 从buf中向fd所代表的文件写入count个字节的数据
- 返回值
成功:写入字符长度,单位字节
失败:-1
向文件file中写入“我很开心。”
#include<fcntl.h>
#include<stdio.h>
#include<unistd.h>
int main()
{
umask(0);
int fd=-1;
fd=open("./file",O_RDWR|O_CREAT,0664);
if(fd==-1){
perror("open error");
}
char* str="我很开心!";
write(fd,str,18);
return 0;
}
read
ssize_t read(int fd, void *buf, size_t count);
- 从文件fd中读取count个字符到buf中
- 返回值
成功:实际读入字符长度,单位字节
失败:-1
#include<fcntl.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
int main()
{
umask(0);
int fd=-1;
fd=open("./file",O_RDWR|O_CREAT,0664);
if(fd==-1){
perror("open error");
}
const char* str="我很开心!";
write(fd,str,strlen("我很开心!"));
char buff[1024];
//读取数据之前,需要让fd指向file文件开头
lseek(fd, 0, SEEK_SET);
read(fd,buff,18);
close(fd);
printf("%s",buff);
return 0;
}
- lseek
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
offset:偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)。
- whence有以下三个选项:
SEEK_SET 将读写位置指向文件头后再增加offset个位移量。
SEEK_CUR 以目前的读写位置往后增加offset个位移量。
SEEK_END 将读写位置指向文件尾后再增加offset个位移量。
编写自主shell进行修改,输入/输出/追加重定向
这里涉及到进程控制的部分知识
#include<stdio.h>
#include<fcntl.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char buf[1024] = { 0 };
while (1)
{
printf("mysell#");
fflush(stdout);
size_t s = read(0, buf, sizeof(buf));
if (s > 0)
{
buf[s - 1] = '\0';
printf("%s\n", buf);
}
char* start = buf;
char* _argv[32];
_argv[0] = buf;
int i = 1;
while (*start)
{
if (*start == ' ')
{
*start = '\0';
start++;
_argv[i++] = start;
}
else
{
start++;
}
}
_argv[i] = NULL;
pid_t pid;
pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);
}
if (pid == 0)
{
int i = 0;
int fd = 0;
for (i = 0; _argv[i] != NULL; i++)
{
if (strcmp(_argv[i], ">") == 0)
{
char* file_name = _argv[i + 1];
_argv[i] = NULL;
close(1);
fd = open(file_name, O_CREAT | O_WRONLY, 0664);
break;
}
}
execvp(_argv[0], _argv);
close(fd);
}
else if (pid > 0)
{
int st = 0;
waitpid(pid, NULL, 0);
}
}
return 0;
}
编写简单的add/sub/mul/div函数,并打包成动/静态库,并分别使用。
计算器静态库
#include"test.h"
#include<stdio.h>
#include<math.h>
int main()
{
int a = 20;
int b = 10;
printf("%d\n",add(a,b));
printf("%d\n",sub(a,b));
printf("%d\n",mul(a,b));
printf("%d\n",div(a,b));
return 0;
}
#ifndef __TEST_H__
#define __TEST_H__
#include<stdio.h>
#include<math.h>
int add(int a,int b);
int sub(int a,int b);
int mul(int a,int b);
int div(int a,int b);
#endif
#include"test.h"
int add(int a,int b)
{
return a+b;
}
int sub(int a,int b)
{
return a-b;
}
int mul(int a,int b)
{
return a*b;
}
int div(int a,int b)
{
return a/b;
}
gcc -c test.c -o test.o
ar -cr lib.a test.o
gcc main.c -L. lib.a
./a.out
计算器动态库
生成动态库
gcc -fPIC -c test.c -o test.o
gcc --share test.o -o libtest.so
动态库也成运行时库,必须放到/lib64
下才能运行,这里在lib64下创建一个libtest.so的软连接
sudo ln -s /home/1/c/base-io/lib/calculator/libtest.so /lib64/libtest.so
sudo ls /lib64|grep libtest
./main