IO进程线程day3(2023.7.31)

一、Xmind整理:

文件描述符概念:

二、课上练习:

练习1:用fread和fwrite实现文件拷贝 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	//以读的方式打开源文件
	FILE* fp_r=fopen("./01_fopen.c","r");
	if(NULL==fp_r)
	{
		ERR_MSG("fopen");
		return -1;
	}
    //以写的方式打开源文件
	FILE* fp_w=fopen("./copy.c","w");
	if(NULL==fp_w)
	{
		ERR_MSG("fopen");
		return -1;
	}

	//读一次写一次,直到文件读取完毕
	char buf[128]="";
	size_t res=0;
	while(1)
	{
		bzero(buf,sizeof(buf));
		//以128为单位,读取1个数据,所当不足128的时候
		//剩下的数据读取不出来,所以这个代码是错误的
		res=fread(buf,1,sizeof(buf),fp_r);
		printf("res=%ld\n",res);
		if(0==res)
			break;
		fwrite(buf,1,res,fp_w);
	}
	printf("拷贝完毕\n");

	//关闭
	fclose(fp_w);
	fclose(fp_r);


	return 0;
}

练习2:time

功能:从1970-1-1日至今的秒数

原型:

 #include <time.h>
 time_t time(time_t *tloc);

参数:

time_t *tloc:若不为空,则1970-1-1日至今的秒数同样会被存储到该指针指向的内存空间中;

返回值:

成功,返回1970-1-1日至今的秒数;
失败,返回((time_t) -1),更新errno;
time_t t = time(NULL);  
printf("%ld\n", t);
time_t pt;                     
time(&pt);
printf("%ld\n", pt);

练习3:localtime

功能:将1970-1-1日至今的秒数转换成日历格式

原型:

#include <time.h>
struct tm *localtime(const time_t *timep);

参数:

time_t *timep: 指定要转换成日历格式的秒数的首地址;

返回值:

成功,返回结构体指针;  vi -t tm可以查看struct tm 成员 或者man手册往下翻
失败,返回NULL;更新errno;      
struct tm {
             int tm_sec;    /* Seconds (0-60) */         秒
             int tm_min;    /* Minutes (0-59) */         分
             int tm_hour;   /* Hours (0-23) */           时
             int tm_mday;   /* Day of the month (1-31) */  日
             int tm_mon;    /* Month (0-11) */             月= tm_mon+1
             int tm_year;   /* Year - 1900 */              年= tm_year+1900
             int tm_wday;   /* Day of the week (0-6, Sunday = 0) */    星期
             int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */   一年中的第几天

          };

例题: 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	/*
	time_t t=time(NULL);
	printf("%ld\n",t);

	time _t pt;
	time(&pt);
	printf("%d\n",pt);
	*/
	time_t t;
	struct tm* info=NULL;

	while(1)
	{
		t=time(NULL);
		info=localtime(&t);
		printf("%d-%02d-%02d %02d:%02d:%02d\r",\
				info->tm_year+1900,info->tm_mon+1,info->tm_mday,\
				info->tm_hour,info->tm_min,info->tm_sec);
		fflush(stdout);
		sleep(1);
	}

	return 0;
}

练习4:文件描述符的总量

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	printf("%d %d %d\n",stdin->_fileno,stdout->_fileno,stderr->_fileno);
	FILE*fp=NULL;
	while(1)
	{
		fp=fopen("./1.txt","w");
		if(NULL==fp)
		{
			ERR_MSG("fopen");
			return -1;
		}
		printf("%d ",fp->_fileno);
		fflush(stdout);
	}
	return 0;
}

练习5:open

功能:打开一个文件

原型:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

参数:

 char *pathname:指定要打开的文件的路径和名字;
 int flags:打开方式
     O_RDONLY     只读, 
     O_WRONLY     只写,
     O_RDWR       读写
 ----以上三种必须包含一种----------
     O_APPEND     追加方式打开,
     O_TRUNC      清空,若文件存在,且是一个普通文件,且以写的方式打开
     O_CREAT      若文件不存在,则创建一个普通文件。
 若有多个选项合成一个打开方式,则用按位或连接:
     "w":O_WRONLY | O_CREAT | O_TRUNC
 mode_t mode:用来指定文件创建的时候的权限,例如:0664
 若flags中包含了O_CREAT或者O_TMPFILE的时候,就必须写mode参数;
 若flags没有O_CREAT或者O_TMPFILE的时候,会忽略mode参数;

返回值:

成功,返回文件描述符,
失败,返回-1,更新errno;

注意:

标准IO中的 r r+ w w+ a a+,用文件IO中的flags进行组合。

 

练习6:umask

the mode of the created file is (mode & ~umask).

文件创建时候的真实权限是 mode & ~umask

mode: 0777 -> 111 111 111 umask?111 111 101=> ~umask -> umask = 000 000 010 = 0002

结果: 0775 ----> 111 111 101

i. umask是什么

文件权限掩码,目的就是影响文件创建时候的权限。可以通过设置umask的值保证某些用户肯定没有某些权限。

ii. 获取umask的值

终端输入:umask

iii. 修改umask的值

1.终端输入: umask 0 只在设置终端有效

2.umask()函数

 #include <sys/types.h>
 #include <sys/stat.h>
 mode_t umask(mode_t mask);
 umask(0);

练习7:close

功能:关闭文件; 释放文件描述符

原型:

#include <unistd.h>
int close(int fd);

参数:

int fd:指定要关闭的文件描述符;

返回值:

成功,返回0;
失败,返回-1,更新errno;

练习8:write

功能:将数据写入到文件中

原型:

 #include <unistd.h>
 ssize_t write(int fd, const void *buf, size_t count);

参数:

int fd:指定要将数据写入到哪个文件中,填对应的文件描述符;
void *buf:指定要输出的数据的首地址,可以是任意类型数据;
size_t count:指定要输出的数据字节数;

返回值:

成功,返回成功输出的字节数;
失败,返回-1,更新errno;

 例题: 创建一个权限是0777的文件,并在数据写入到文件中

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	//将本程序的umask的值修改成0
	umask(0);
	int fd=open("./open.txt",O_WRONLY|O_CREAT|O_TRUNC,0777);
	if(fd<0)
	{
		ERR_MSG("open");
		return -1;
	}
	printf("open success\n");

	ssize_t res=0;
	char buf[]="hello world";
	res=write(fd,buf,sizeof(buf));
	printf("res=%ld\n",res);

	if(close(fd)<0)
	{
		ERR_MSG("close");
		return -1;
	}
	printf("close success\n");
	return 0;
}

注意: 

write函数指定写多少个字节,就会从内存中拿多少个字节,写入到文件中,即使越界

练习9:read

功能:从文件中读取数据

原型:

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

参数:

int fd:指定要从哪个文件中读取数据,填对应的文件描述符;
void *buf:指定要将读取到的数据存储到那块空间中,可以是任意类型数据;
size_t count:指定要读取的数据字节数;

返回值:

 >0, 成功,返回成功读取的字节数;
 =0, 文件读取完毕;
 =-1, 失败,返回-1,更新errno;

 例题1: read的使用

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	//将本程序的umask的值修改成0
	umask(0);
	int fd=open("./01_fileno.c",O_RDONLY);
	if(fd<0)
	{
		ERR_MSG("open");
		return -1;
	}
	printf("open success\n");

	ssize_t res=0;
	char buf[128]="";

	while(1)
	{
		bzero(buf,sizeof(buf));
		res=read(fd,buf,sizeof(buf));
		if(0==res)
		{
			break;
		}
		//将数据写到终端,写的个数为实际读取到的字节数
		write(1,buf,res);
	}

#if 0
	while(1)
	{
		bzero(buf,sizeof(buf));
		/***************************************/
		//由于后续打印的是使用%s打印,所以需要保留一个\0位置
		//防止%s打印的时候越界少\0位 
		res=read(fd,buf,sizeof(buf)-1);
		if(0==res)
		{
			break;
		}
		printf("%s",buf);    //%s打印直到遇到\0位置
	}
#endif
	printf("读取完毕\n");
	if(close(fd)<0)
	{
		ERR_MSG("close");
		return -1;
	}
	printf("close success\n");

	return 0;
}

 例题2:用read和write函数实现,拷贝图片

 提示:1.ls-l查看图片类型

            2.eog  图片--->打开图片

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	//以读的方式打开源文件
	int fd_r=open("./1.png",O_RDONLY);
	if(fd_r<0)
	{
		ERR_MSG("open");
		return -1;
	}
	printf("open success\n");
	//以写的方式打开目标文件
	int fd_w=open("./2.png",O_WRONLY|O_CREAT|O_TRUNC,0664);
	if(fd_w<0)
	{
		ERR_MSG("open");
		return -1;
	}

	ssize_t res=0;
	char buf[128]="";
	//读一次写一次
	while(1)
	{
		bzero(buf,sizeof(buf));
		res=read(fd_r,buf,sizeof(buf));
		if(0==res)
		{
			break;
		}
		//读多少个就写多少个
		if(write(fd_w,buf,res)<0)
		{
			ERR_MSG("write");
			return -1;
		}
	}
	printf("拷贝完成\n");
	//关闭
	if(close(fd_r)<0)
	{
		ERR_MSG("close");
		return -1;
	}
	if(close(fd_w)<0)
	{
		ERR_MSG("close");
		return -1;
	}

	printf("close success\n");
	return 0;
}

练习10:lseek

功能:修改文件偏移量

原型:

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

参数:

int fd:文件描述符;
off_t offset: 距离whence参数指定的偏移量。往前偏移填负数, 往后偏移填正数
int whence:
    SEEK_SET,  文件开头位置
    SEEK_CUR,  文件当前位置
    SEEK_END   文件结尾位置

返回值:

成功,修改偏移量后,文件当前位置距离文件开头的偏移量;
失败,返回-1,更新errno;    
//计算文件大小
off_t size = lseek(fd_r, 0, SEEK_END);
printf("size=%ld\n", size);

例题:lseek的使用 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	//以读的方式打开源文件
	int fd_r=open("./1.png",O_RDONLY);
	if(fd_r<0)
	{
		ERR_MSG("open");
		return -1;
	}
	//计算文件大小
	off_t size=lseek(fd_r,0,SEEK_END);
	printf("size=%ld\n",size);
	//关闭
	close(fd_r);
	return 0;
}

注意: 

若偏移量在文件开头,能否继续往前偏移 ---> 不行

若偏移量在文件结尾,能否继续往后偏移 ---> 可以

练习11:获取文件属性

练习12:stat

功能:获取文件的属性

原型:

 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 int stat(const char *pathname, struct stat *statbuf);

参数:

char *pathname:指定要获取属性的文件路径以及名字;
struct stat *statbuf:存储获取到的属性;

返回值:

成功,返回0;
失败,返回-1,更新errno;
    
vi -t stat 或者 man手册往下翻
struct stat 
{
 ino_t     st_ino;         /* Inode number */            inode号
 mode_t    st_mode;        /* File type and mode */      文件类型和权限
 nlink_t   st_nlink;       /* Number of hard links */    硬链接数
 uid_t     st_uid;         /* User ID of owner */        用户的uid
 gid_t     st_gid;         /* Group ID of owner */       组用户的gid
 off_t     st_size;        /* Total size, in bytes */    文件大小

 struct timespec st_atim;  /* Time of last access */         最后一次被访问的时间
 struct timespec st_mtim;  /* Time of last modification */   最后一次被修改的时间
 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
};

提取文件的权限:

mode_t st_mode 本质上是一个unsigned int类型,里面存储了文件的类型和权限。

st_mode中其中低9bits存储了文件的权限:[0bit - 8bit]

例题:文件权限提取 

#include <stdio.h>
#include <head.h>

void get_filePermission(mode_t m)   //mode_t m = buf.st_mode
{
    if((m & 0400) != 0)
        putchar('r');
    else
        putchar('-');

    if((m & 0200) != 0)                                      
        putchar('w');
    else
        putchar('-');

    if((m & 0100) != 0)
        putchar('x');
    else
        putchar('-');

    ///
    if((m & 0040) != 0)
        putchar('r');
    else
        putchar('-');

    if((m & 0020) != 0)
        putchar('w');
    else
        putchar('-');

    if((m & 0010) != 0)
        putchar('x');
    else
        putchar('-');
    

    if((m & 0004) != 0)
        putchar('r');
    else
        putchar('-');

    if((m & 0002) != 0)
        putchar('w');
    else
        putchar('-');

    if((m & 0001) != 0)
        putchar('x');
    else
        putchar('-');

    return;
}
int main(int argc, const char *argv[])
{
    struct stat buf;
    if(stat("./01_fileno.c", &buf) < 0)
    {
        ERR_MSG("stat");
        return -1;
    }

    //文件的类型和权限
    printf("mode: 0%o\n", buf.st_mode);
    get_filePermission(buf.st_mode);

    //文件的硬链接数
    printf("link: %ld\n", buf.st_nlink);

    //文件的所属用户
    printf("uid: %d\n", buf.st_uid);

    //文件所属组用户
    printf("gid: %d\n", buf.st_gid);

    //文件大小
    printf("size: %ld\n", buf.st_size);

    //文件的修改时间
    printf("time: %ld\n", buf.st_ctime);

    //文件的名字
	
    return 0;
}

三、课后作业:

1.用read函数计算文件的大小 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
	int fd = open("./1.png",O_RDONLY);
	if(fd < 0)
	{
		ERR_MSG("open");
		return -1;
	}
	printf("open success\n");

	off_t size = lseek(fd,0,SEEK_END);
	printf("size=%ld\n",size);

	char c;
	ssize_t res = 0;
	int count = 0;
	lseek(fd,0,SEEK_SET);
	while(1)
	{
		res = read(fd,&c,1);
		if(0 == res)
			break;
		count++;
	}
	printf("count=%d\n",count);

	if(close(fd) < 0)
	{
		ERR_MSG("close");
		return -1;
	}
	printf("close success\n");

	return 0;
}

2.将课上的文件权限提取修改成循环方式

#include <stdio.h>
#include <head.h>

void get_filePermission(mode_t m)
{
	long x=0400;
	char c[]="rwx";
	int count=0;
	while(x)
	{
		if((m & x) != 0)
			putchar('r');
		else
			putchar('-');
		x=x>>1;
		if((m & x) != 0)                                      
			putchar('w');
		else
			putchar('-');
		x=x>>1;
		if((m & x) != 0)
			putchar('x');
		else
			putchar('-');
		x=x>>1;
	}

	return;
}
int main(int argc, const char *argv[])
{
    struct stat buf;
    if(stat("./01_fileno.c", &buf) < 0)
    {
        ERR_MSG("stat");
        return -1;
    }

    //文件的类型和权限
    printf("mode: 0%o\n", buf.st_mode);
    get_filePermission(buf.st_mode);

    //文件的硬链接数
    printf("link: %ld\n", buf.st_nlink);

    //文件的所属用户
    printf("uid: %d\n", buf.st_uid);

    //文件所属组用户
    printf("gid: %d\n", buf.st_gid);

    //文件大小
    printf("size: %ld\n", buf.st_size);

    //文件的修改时间
    printf("time: %ld\n", buf.st_ctime);
	
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/53506.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Chapter 9: Lists | Python for Everybody 讲义笔记_En

文章目录 Python for Everybody课程简介ListsA list is a sequenceLists are mutableTraversing a listList operationsList slicesList methodsDeleting elementsLists and functionsLists and stringsParsing linesObjects and valuesAliasingList argumentsDebuggingGlossar…

Windows10系统还原操作

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 复制了下虚拟机的Win10系统&#xff0c;但其中有一些软件&#xff0c;想实现类似手机的格式化出厂操作&#xff0c;下面记录Windows10系统的还原操作。 一、系统环境&#xff1a; 虚拟机内的Windows10&#xff0c;64…

R730服务器用光盘安装系统(Esxi系统)

准备阶段&#xff1a;dell R730服务器&#xff0c;本教程一般适用于dell所有服务器&#xff0c;移动光盘&#xff0c;光碟做好镜像系统。在这里我安装的系统是Esxi系统&#xff0c;其他操作系统类似&#xff0c;只是安装的步骤不一样而已。 1、将系统盘插入光驱(移动光盘)&…

测试|自动化测试(了解)

测试|自动化测试&#xff08;了解&#xff09; 1.什么是自动化测试☆☆☆☆ 自动化测试相当于把人工测试手段进行转换&#xff0c;让代码执行。 2.自动化测试的分类☆☆☆☆ 注&#xff1a;这里只是常见的自动化测试&#xff0c;并不全部罗列。 1.单元自动化测试 其中Java…

3分钟学会设计模式 -- 单例模式

►单例模式 ►使用场景 在编写软件时&#xff0c;对于某些类来说&#xff0c;只有一个实例很重要。例如&#xff0c;一个系统中可以存在多个打印任务&#xff0c;但是只能有一个正在工作的任务&#xff1b;一个系统中可以多次查询数据库&#xff0c;但是只需要一个连接&#x…

Rust vs Go:常用语法对比(九)

题图来自 Golang vs Rust - The Race to Better and Ultimate Programming Language 161. Multiply all the elements of a list Multiply all the elements of the list elements by a constant c 将list中的每个元素都乘以一个数 package mainimport ( "fmt")func …

4通道高速数据采集卡推荐哪些呢

FMC141是一款基于VITA57.4标准的4通道2.8GSPS/2.5GSPS/1.6GSPS采样率16位DA播放FMC子卡&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.4与VITA57.1规范&#xff0c;16通道的JESD204B接口通过FMC连接器连接至FPGA的高速串行端口。 该板卡采用TI公司的DAC39J84芯片&#x…

重生之我要学C++第六天

这篇文章的主要内容是const以及权限问题、static关键字、友元函数和友元类&#xff0c;希望对大家有所帮助&#xff0c;点赞收藏评论支持一下吧&#xff01; 更多优质内容跳转&#xff1a; 专栏&#xff1a;重生之C启程(文章平均质量分93) 目录 const以及权限问题 1.const修饰…

DP-GAN-生成器代码

在train文件中&#xff0c;对生成器和判别器分别进行更新&#xff0c;根据loss的不同&#xff0c;分别计算对于的损失&#xff1a; loss_G, losses_G_list model(image, label, "losses_G", losses_computer)loss_D, losses_D_list model(image, label, "los…

给初学嵌入式的菜鸟一点建议.学习嵌入式linux

学习嵌入式&#xff0c;我认为两个重点&#xff0c;cpu和操作系统&#xff0c;目前市场是比较流行arm&#xff0c;所以推荐大家学习arm。操作系统很多&#xff0c;我个人对开始学习的人&#xff0c;特别不是计算机专业的&#xff0c;推荐学习ucos。那是开源的&#xff0c;同时很…

ALLEGRO之Place

本文主要讲述了ALLEGRO的Place菜单。 &#xff08;1&#xff09;Manually&#xff1a;手动放置&#xff0c;常用元器件放置方法&#xff1b; &#xff08;2&#xff09;Quickplace&#xff1a;快速放置&#xff1b; &#xff08;3&#xff09;Autoplace&#xff1a;自动放置&a…

Linux6.16 Docker consul的容器服务更新与发现

文章目录 计算机系统5G云计算第四章 LINUX Docker consul的容器服务更新与发现一、consul 概述1.什么是服务注册与发现2.什么是consul 二、consul 部署1.consul服务器2.registrator服务器3.consul-template4.consul 多节点 计算机系统 5G云计算 第四章 LINUX Docker consul的…

Linux虚拟机安装tomcat(图文详解)

目录 第一章、xshell工具和xftp的使用1.1&#xff09;xshell下载与安装1.2&#xff09;xshell连接1.3&#xff09;xftp下载安装和连接 第二章、安装tomcat1.1&#xff09;关闭防火墙&#xff0c;传输tomcat压缩包到Linux虚拟机12&#xff09;启动tomcat 第一章、xshell工具和xf…

Git 版本管理使用-介绍-示例

文章目录 Git是一种版本控制工具&#xff0c;它可以帮助程序员组织和管理代码的变更历史Git的使用方式&#xff1a;常见命令安装Git软件第一次上传分支删除分支 Git是一种版本控制工具&#xff0c;它可以帮助程序员组织和管理代码的变更历史 以下是Git的基本概念和使用方式&am…

【Git系列】分支操作

&#x1f433;分支操作 &#x1f9ca;1. 什么是分支&#x1f9ca;2. 分支的好处&#x1f9ca;3. 分支操作&#x1fa9f;3.1 查看分支&#x1fa9f;3.2 创建分支&#x1fa9f;3.3 切换分支 &#x1f9ca;4. 分支冲突&#x1fa9f;4.1 环境准备&#x1fa9f;4.2 分支冲突演示 &am…

01 Excel常用高频快捷键汇总

目录 一、简介二、快捷键介绍2.1 常用基本快捷键1 复制&#xff1a;CtrlC2 粘贴&#xff1a;CtrlV3 剪切&#xff1a;CtrlX4 撤销&#xff1a;CtrlZ5 全选&#xff1a;CtrlA 2.2 常用高级快捷键1 单元格内强制换行&#xff1a;AltEnter2 批量输入相同的内容&#xff1a;CtrlEnt…

机器学习-Basic Concept

机器学习(Basic Concept) videopptblog Where does the error come from? 在前面我们讨论误差的时候&#xff0c;我们提到了Average Error On Testing Data是最重要的 A more complex model does not lead to better performance on test data Bias And Variance Bias(偏差) …

排序算法(冒泡排序、选择排序、插入排序、希尔排序、堆排序、快速排序、归并排序、计数排序)

&#x1f355;博客主页&#xff1a;️自信不孤单 &#x1f36c;文章专栏&#xff1a;数据结构与算法 &#x1f35a;代码仓库&#xff1a;破浪晓梦 &#x1f36d;欢迎关注&#xff1a;欢迎大家点赞收藏关注 文章目录 &#x1f353;冒泡排序概念算法步骤动图演示代码 &#x1f34…

数学建模学习(7):Matlab绘图

一、二维图像绘制 1.绘制曲线图 最基础的二维图形绘制方法&#xff1a;plot -plot命令自动打开一个图形窗口Figure&#xff1b; 用直线连接相邻两数据点来绘制图形 -根据图形坐标大小自动缩扩坐标轴&#xff0c;将数据标尺及单位标注自动加到两个坐标轴上&#xff0c;可自定…

【Linux】sed修改文件指定内容

sed修改文件指定内容&#xff1a; 参考&#xff1a;(5条消息) Linux系列讲解 —— 【cat echo sed】操作读写文件内容_shell命令修改文件内容_星际工程师的博客-CSDN博客