Linux基础(六) 系统IO函数

使用file命令看文件格式

root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# file app
app: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=48cafae57ae4074bc8068d943439bdcc2ae85fa3, not stripped

ELF格式是linux下的可执行程序格式

1 open()

1.1 打开文件

一下是Linux下调用系统函数来打开文件的示例
首先定义open.c文件,并把文件路径指向一个不存在的文件地址

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
	int fd;
	//打开已经存在的文件
	fd = open("notExistFile",O_RDWR);
	if(fd == -1)
	{
		perror("open file");
		exit(1);
	}

	//关闭文件
	int ret = close(fd);
	printf("ret = %d\n", ret);
	if(ret == -1)
	{
		perror("close file");
		exit(1);
	}
}

编译open.c并执行后,会提示文件找不到

root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# gcc open.c -o open
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ls
open  open.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ./open 
open file: No such file or directory

修改文件路径为已经存在的路径

	fd = open("hello.c",O_RDWR);

重新编译并执行

root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ls
hello.c  open.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# gcc open.c -o open
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ls
hello.c  open  open.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ./open
ret = 0

1.2 创建文件

0777表示文件权限

	//创建新文件
	fd = open("hello1.c", O_RDWR | O_CREAT, 0777);
	if(fd == -1)
	{
		perror("open file");
		exit(1);
	}
	printf("fd = %d\n",fd);

open.c全部代码

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
	int fd;
	//打开已经存在的文件
	fd = open("hello.c",O_RDWR);
	if(fd == -1)
	{
		perror("open file");
		exit(1);
	}

	//创建新文件
	fd = open("hello1.c", O_RDWR | O_CREAT, 0777);
	if(fd == -1)
	{
		perror("open file");
		exit(1);
	}
	printf("fd = %d\n",fd);

	//关闭文件
	int ret = close(fd);
	printf("ret = %d\n", ret);
	if(ret == -1)
	{
		perror("close file");
		exit(1);
	}
}

编译并执行

root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ls
hello.c  open.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# gcc open.c -o open
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ls
hello.c  open  open.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ./open
fd = 4
ret = 0
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ls
hello1.c  hello.c  open  open.c

1.3 文件权限的计算方式

可以看到文件的权限并不是777而是755

-rwxr-xr-x 1 root root    0 Jan 27 23:16 hello1.c

文件的实际权限:
指定的权限 & 本地掩码取反 = 实际的文件权限
本地掩码获取方式

root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# umask
0022
			  777的二进制为 ---> 111 111 111
 本地掩码为 000 010 010 取反 ---> 111 101 101

结果为111 101 101 即为 755
掩码的值可以改

root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# umask 002
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# umask
0002

1.4 判断文件已经存在

只需要多加一个条件

fd = open("hello1.c", O_RDWR | O_CREAT | O_EXCL, 0777);
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# gcc open.c -o open
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ./open
open file: File exists

1.5 将文件截断为0

首先修改open函数的参数

	fd = open("hello1.c", O_RDWR | O_TRUNC );

查看hello1.c文件中的内容,并执行open程序

root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ls
hello1.c  hello.c  open.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# cat hello1.c
this content in hello1.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# gcc open.c -o open
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ls
hello1.c  hello.c  open  open.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# ./open
fd = 4
ret = 0

再次查看hello1.c文件中的内容,可以看到文件内容为空。

root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# cat hello1.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/c_library# 

2 read() write()

1 定义read.c文件

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
	//打开一个已经存在文件
	int fd = open("english.txt", O_RDONLY);
	if(fd == -1)
	{
		perror("open");
		exit(1);
	}

	//创建一个新文件 执行写入操作
	int fd1 = open("newfile", O_CREAT | O_WRONLY, 0664);
	if(fd1 == -1)
	{
		perror("open1");
		exit(1);
	}

	//read file
	char buf[1024] = {0};
	int count = read(fd, buf, sizeof(buf));
	if(count == -1)
	{
		perror("read");
		exit(1);
	}

	while(count)
	{
		//将读出的数据写入另一个文件中
		int ret = write(fd1, buf, count);
		printf("write bytes %d\n", ret);
		//continuee read file
		count = read(fd, buf, sizeof(buf));
	}

	//close file
	close(fd);
	close(fd1);

}

2 编译并执行read.c

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/02_read_write# ls
english.txt  read.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/02_read_write# gcc read.c -o read
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/02_read_write# ls
english.txt  read  read.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/02_read_write# ./read 
write bytes 1024
write bytes 1024
write bytes 1024
write bytes 1024
write bytes 1024
write bytes 1024
write bytes 1024
write bytes 1024
write bytes 367
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/02_read_write# ls
english.txt  newfile  read  read.c

3 可以看到生成的newfile和english.txt的文件大小相同

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/02_read_write# ls -l 
total 40
-rw-r--r-- 1 root root 8559 Jan 29 15:03 english.txt
-rw-r--r-- 1 root root 8559 Jan 29 21:20 newfile

3 lseek()

1 定义lseek.c文件

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
	int fd = open("test_lseek.txt", O_RDWR);
	if(fd == -1)
	{
		perror("open file");
		exit(1);
	}
	
	int ret = lseek(fd, 0, SEEK_END);
	printf("file length = %d\n", ret);

	//文件拓展 指定偏移量
	ret = lseek(fd, 2000, SEEK_END);
	printf("return value %d\n", ret);

	//实现文件拓展 需再做一次写操作
	write(fd, "a", 1);
	close(fd);
	return 0;
}

2 编译lseek.c文件并执行

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/03_lseek# gcc lseek.c -o lseek
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/03_lseek# ls
lseek  lseek.c  test_lseek.txt
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/03_lseek# ./lseek 
file length = 18
return value 2018

可以看到之前是18个字,调用lseek函数再偏移2000后,总偏移量为2018。
完成文件的拓展以后必须再执行写操作。

4 stat()

4.1 stat命令

使用stat命令查看文件信息

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/04_stat# stat english.txt 
  File: english.txt
  Size: 8559      	Blocks: 24         IO Block: 4096   regular file
Device: fc01h/64513d	Inode: 1321644     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2020-01-29 21:48:45.112829927 +0800
Modify: 2020-01-29 21:48:43.688821858 +0800
Change: 2020-01-29 21:48:43.688821858 +0800
 Birth: -

4.2 stat函数简介

通过man文档,查看stat函数的使用

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/04_stat# man 2 stat
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <unistd.h>

	  //statbuf是传出参数
       int stat(const char *pathname, struct stat *statbuf); 

以下是stat结构体

struct stat {
				//1 文件的设备编号
               dev_t     st_dev;         /* ID of device containing file */
               //2 节点
               ino_t     st_ino;         /* Inode number */
				//3 文件的类型和存取权限
               mode_t    st_mode;        /* File type and mode */
               //4 文件的硬链接数量
               nlink_t   st_nlink;       /* Number of hard links */
               //5 用户id
               uid_t     st_uid;         /* User ID of owner */
				//6 组id
               gid_t     st_gid;         /* Group ID of owner */
               //7 若此文件为设备文件 则为其设备编号
               dev_t     st_rdev;        /* Device ID (if special file) */
				//8 文件的字节大小
               off_t     st_size;        /* Total size, in bytes */
               //9 块大小
               blksize_t st_blksize;     /* Block size for filesystem I/O */
               // 10 块数量
               blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */

               /* Since Linux 2.6, the kernel supports nanosecond
                  precision for the following timestamp fields.
                  For the details before Linux 2.6, see NOTES. */
			   // 11 最后一次访问时间
               struct timespec st_atim;  /* Time of last access */
               //12 最后一次修改时间
               struct timespec st_mtim;  /* Time of last modification */
               //13 最后一次改变时间
               struct timespec st_ctim;  /* Time of last status change */

           #define st_atime st_atim.tv_sec      /* Backward compatibility */
           #define st_mtime st_mtim.tv_sec
           #define st_ctime st_ctim.tv_sec
           };

根据stat结构体和stat()函数可知,通过调用stat()函数,并传进去stat的指针,stat()函数内部会给stat结构体赋值。stat结构体包含了文件的各种信息,所以此时可以通过stat结构体来获取文件的信息。

4.3 stat函数使用

以下是通过获取文件的大小来示例stat函数的使用。
当然也可以文件的其他信息。这里只是获取文件大小。
1 定义stat.c文件

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
	if(argc < 2)
	{
		printf("./test.out filename\n");
		exit(1);
	}
	struct stat st;
	int ret = stat(argv[1], &st);
	if(ret == -1)
	{
		perror("stat");
		exit(1);
	}

	//1 获取文件大小
	int size = (int)st.st_size;
	printf("file size = %d\n", size);
}

2 编译stat.c文件

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/04_stat# gcc stat.c -o stat
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/04_stat# ls
english.txt  stat  stat.c

3 执行stat程序,查看文件大小

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/04_stat# ./stat english.txt 
file size = 8559

可以看到和ls -l命令输出的文件大小一致

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/04_stat# ls -l english.txt 
-rw-r--r-- 1 root root 8559 Jan 29 21:48 english.txt

4 lstat()函数
如果文件是软连接:
则lstat函数获取到的是软连接文件本身的大小(不穿透)
而stat函数则会获取到穿透文件的大小,即软连接指向的文件大小。

5 access()

access函数是用来获取指定文件的读写执行权限的。
以下以获取文件的写权限为示例
1 定义access.c文件

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
	if(argv < 2)
	{
		printf("a.out filename\n");
		exit(1);
	}

	int ret = access(argv[1], W_OK);
	if(ret == -1)
	{
		perror("error");
		exit(1);
	}
	printf("you can write this file.\n");
	return 0;
}

2 编译.c文件

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/05_access# ls
access.c  english.txt
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/05_access# gcc access.c -o access
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/05_access# ls
access  access.c  english.txt

3 执行程序

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/05_access# ./access english.txt 
you can write this file.

6 chmod()

修改文件权限
1 定义chmod.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

int main(int argc, char* argv[])
{
	if(argc < 2)
	{
		printf("a.out filename\n");
		exit(1);
	}

	int ret = chmod(argv[1], 0755);
	if(ret == -1)
	{
		perror("chmod");
		exit(1);
	}
	return 0;
}

2 编译chmod.c

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/06_chmod# ls -l
total 16
-rw-r--r-- 1 root root  256 Jan 30 07:54 chmod.c
-rw-r--r-- 1 root root 8559 Jan 30 07:53 english.txt
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/06_chmod# gcc chmod.c -o chmod
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/06_chmod# ls
chmod  chmod.c  english.txt

3 执行

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/06_chmod# ./chmod  english.txt 
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/06_chmod# ls -l
total 28
-rwxr-xr-x 1 root root 8432 Jan 30 07:54 chmod
-rw-r--r-- 1 root root  256 Jan 30 07:54 chmod.c
-rwxr-xr-x 1 root root 8559 Jan 30 07:53 english.txt

可以看到执行前和执行后对应的权限发生了变化。

7 unlink()

创建临时文件
以下示例是
通过创建文件,然后将文件中的内容输出到屏幕中。然后再删除文件来展示unlink()函数的用法。

1 创建unlink.c文件

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

int main()
{
	int fd = open("tempfile", O_CREAT | O_RDWR, 0664);
	if(fd == -1)
	{
		perror("open");
		exit(1);
	}

	//删除临时file
	int ret = unlink("tempfile");

	//write file
	write(fd, "hello\n", 6);

	//重置文件指针
	lseek(fd, 0, SEEK_SET);

	//read file
	char buf[24] = {0};
	int len = read(fd, buf, sizeof(buf));

	//将读出来的内容写到屏幕上
	write(1, buf, len);

	//close file
	close(fd);
	return 0;
}

2 编译执行.c文件

root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/07_unlink# gcc unlink.c -o unlink
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/07_unlink# ls
unlink  unlink.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/07_unlink# ./unlink
hello
root@iZ2ze9ftqv2b7zbety6qd8Z:~/linux_learn/c_library/07_unlink# ls
unlink  unlink.c

可以看到执行后,temfile中的内容输出到了屏幕上,但是tempfile文件并不存在,说明tempfile文件被删除了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值