文件操作(Linux系统调用)


本片博客会粘贴部分代码,想要了解更多代码信息,可访问 小编的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

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值