使用mmap将文件映射到虚拟地址空间进行操作


使用mmap将文件映射到进程的虚拟地址空间,对内存的操作,直接反应到文件中。

相关概念:

Linux od命令用于输出文件内容。

  • od指令会读取所给予的文件的内容,并将其内容以八进制字码呈现出来。

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

  • 头文件需要包含<sys/mman.h>
  • 功能:映射文件或设备到内存空间
  • 参数:
    • addr:映射后的虚拟地址空间的地址(一般为NULL)

    • length:映射的长度

    • prot:

      • PROT_NONE Pages may not be accessed.
      • PROT_EXEC Pages may be executed.
      • PROT_READ Pages may be read.
      • PROT_WRITE Pages may be written.
    • flags:

      • MAP_SHARED:
      • MAP_PRIVATE:
      • MAP_ANONYMOUS: 不支持文件映射
    • fd:-1

    • offset:0

  • 返回值:
    • MAP_FAILED 错误 errno被设置
      成功返回映射区域的地址

int munmap(void *addr, size_t length);

  • 功能:解除内存映射
  • 参数:
    • addr:是mmap(2)的返回值
    • length:同mmap(2)函数中的length
  • 返回值:
    • 0 成功
    • -1 失败 errno被设置

代码参考:

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

int main(int argc,char *argv[]){
	int fd;
	//以读写方式打开文件
	fd=open(argv[1],O_RDWR);
	if(fd==-1){
		perror("open");
		return 1;
	}
	//建立映射
	void *p=mmap(NULL,6,\
		PROT_READ|PROT_WRITE,
		MAP_SHARED,fd,0);
	if(p==MAP_FAILED){
		perror("mmap");
		return 2;
	}
	printf("success...\n");
	//关闭文件
	close(fd);
	//对内存的操作
	int *q=(int *)p;
	q[0]=0x30313233;
	//解除映射
	munmap(p,6);
	return 0;
}

执行验证

在这里插入图片描述

代码获取文件的元数据

文件的元数据

文件的元数据就是文件的属性,使用

ls -l [文件名]#查看

在这里插入图片描述

相关使用函数

  • 如何获取一个文件的元数据?
    使用系统调用stat(2)获取文件的元数据。
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
功能:获取文件的状态信息
参数:
path:指定了文件的名字
buf:将文件的状态信息存储到buf指定的空间里。
返回值:
-1  错误   errno被设置
0  成功
struct stat{
	dev_t   st_dev;  /* ID of device containing file */
        ino_t   st_ino;     /* inode number */
        mode_t  st_mode;    /* protection */
        nlink_t st_nlink;   /* number of hard links */
        uid_t   st_uid;     /* user ID of owner */
        gid_t   st_gid;     /* group ID of owner */
        dev_t   st_rdev;    /* device ID (if special file) */
        off_t   st_size;    /* total size, in bytes */
	blksize_t st_blksize; /* blocksize for file system I/O */
        blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
        time_t    st_atime;   /* time of last access */
        time_t    st_mtime;   /* time of last modification */
        time_t    st_ctime;   /* time of last status change */
};
  • 如何将uid的数字转换为用户的名字?
    getpwuid(3)
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
功能:获取用户的信息
参数:
uid:指定用户的uid
返回值:
返回一个指向struct passwd结构体的指针
NULL 找不到这个用户的信息或错误产生 如果是产生错误,errno被设置

/etc/passwd文件的内容
这个文件里存放的是系统的所有用户的信息。

struct passwd {
       char   *pw_name;       /* username */
       char   *pw_passwd;     /* user password */
       uid_t   pw_uid;        /* user ID */
       gid_t   pw_gid;        /* group ID */
       char   *pw_gecos;      /* user information */
       char   *pw_dir;        /* home directory */
       char   *pw_shell;      /* shell program */
};
  • 如何通过gid获取组名?
getgrnam(3)
getgrgid(3)
#include <sys/types.h>
#include <grp.h>
struct group *getgrgid(gid_t gid);
功能:获取一条组信息
参数:
gid:指定的组id
返回值:
返回一个指向struct group结构体的指针
NULL 找不到这个组的信息或错误产生 如果是产生错误,errno被设置.
struct group{
	       char   *gr_name;       /* group name */
           char   *gr_passwd;     /* group password */
           gid_t   gr_gid;        /* group ID */
           char  **gr_mem;        /* group members */
};
  • 组信息存放在/etc/group文件中
    在这里插入图片描述

  • 将长整型的时间转换为字符串格式的时间

ctime(3)
#include <time.h>
char *ctime(const time_t *timep);
功能:将长整型的时间转换为字符串格式
参数:
timep:长整型的时间
返回值:
NULL   错误
字符串

代码实现

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
int main(int argc,char *argv[]){
	struct stat sbuf;
	struct passwd *p;
	int s; 
	//获取指定文件的元数据
	s=stat(argv[1],&sbuf);
	if(s==-1){//获取文件的元数据失败
		perror("stat");
		return 1;
	}
	printf("size:%ld\n",sbuf.st_size);
	printf("hard links:%d\n",\
		sbuf.st_nlink);		
	printf("inode number:%lu\n",\
		sbuf.st_ino);
	//printf("uid:%d\n",sbuf.st_uid);
	p=getpwuid(sbuf.st_uid);
	if(p==NULL){
		return 2;
	}
	printf("username:%s\n",p->pw_name);
	//printf("gid:%d\n",sbuf.st_gid);
	struct group *q=\
		getgrgid(sbuf.st_gid);
	printf("group name:%s\n",q->gr_name);
	char *st=ctime(&sbuf.st_atime);
	printf("time:%s\n",st);
	printf("mode:%o\n",sbuf.st_mode);
#if 0
	if(S_ISREG(sbuf.st_mode))printf("-");
	if(S_ISDIR(sbuf.st_mode))printf("d");
	printf("\n");
#endif
	switch(sbuf.st_mode&S_IFMT){
		case S_IFREG:
			printf("-");
			break;
		case S_IFDIR:
			printf("d");
			break;
		default:
			break;
	}
	printf("\n");
	//打印出属主的权限
	if(sbuf.st_mode&S_IRUSR)
		printf("r");
	else 
		printf("-");
	if(sbuf.st_mode&S_IWUSR)
		printf("w");
	else
		printf("-");
	printf("\n");

	
	
#if 0
	switch(sbuf.st_mode&00700){
		case S_IRUSR:
			printf("r");
			break;
		case S_IWUSR:
			printf("w");
			break;
		case S_IXUSR:
			printf("x");
			break;
		default:
			break;
	}
#endif
	return 0;
}

执行

在这里插入图片描述

发布了102 篇原创文章 · 获赞 27 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_37596943/article/details/104165531