使用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文件被删除了。