Linux——makefile IO基础 文件描述符

一、make与makefile

        1.回顾:
                目标的语法
                目标名:依赖目标
                        @命令
                        @命令
                        
                make的命令行使用
                        make -f make脚本文件  目标名
        2.目标的划分
                目标依赖
        
        3.默认规则:
                a.不指定目标,执行第一个目标
                b.不指定make文件,默认文件是makefile Makefile
                        makefile优先
        4.目标的调用规则:(make把目标当作文件)
                make执行目标:
                        搜索与目标相同的文件
                        如果文件存在,则判定日期。
                        日期最新,则停止执行,输出提示
                        日期不是最新,则进行执行。
                        
                        
                        比较:当前目标与依赖目标
        5.建议:
                只要有文件输出,就把任务作为一个目标
                ,并且把输出的文件作为目标名。
                
        6.潜规则(不建议)
                .c目标与.o目标。
                查找.o目标,目标不存在,就把.o替换成.c
                如果.c存在,实施潜规则:直接调用gcc把.c执为.o
        7.变量  可以在Makefile中使用变量(自己定义的或者环境变量)
                变量名=值 值
                
                $(变量名)或者${变量}        
        8.伪目标:
                不把目标作为文件处理的目标称为伪目标
                声明伪目标        
没有介绍:
        1.make的配置
        2.make的变量的操作函数
        3.多make文件使用

二、环境变量

        1.使用main的参数
        int main(int args,char *argv[],char **arge)
        {
        }
        命令行参数argv与环境行arge都是字符串数组.

        约定:最后一个字符串是NULL/0

env.c

#include <stdio.h>
#include <unistd.h>
extern char **environ;//外部变量 系统定义
int main(/*int args,char *argv[],char*arge[]*/)
{
	/*打印全部的环境变量
	while(*arge)
	{
		printf("%s\n",*arge);
		arge++;
	}
	*/
	/*
	int i=0;
	while(arge[i])
	{
		printf("%s\n",arge[i]);
		i++;
	}
	*/
	while(*environ)
	{
		printf("%s\n",*environ);
		environ++;
	}
}


        2.在C的标准库提供:外部变量

            extern char **environ;
        3.修改获取某个环境变量
                getenv/setenv/unsetenv

environ.c

#include <stdlib.h>
#include <stdio.h>
main()
{
	char *val;
	val=getenv("PATH");
	printf("%s\n",val);
}          

三、IO的基础

        1.认识内核对象
                不允许访问内核设备和内存,
                但可以通过内核系统函数去访问.
                对每个内核对象进行编号ID.
                如果访问内核对象,只能通过ID.
                编程模型:
                        申请得到一个ID
                        在内核系统函数中使用ID得到对应内核对象数据
        2.怎么访问文件
                使用函数,传递一个文件,系统打开文件,加载文件数据,
                返回一个ID.
                使用函数,传递ID,得到数据.
                使用函数传递ID,告诉系统释放文件.
                                
                ID:文件描述符号.file description (fd)
                

                每个程序执行的时候都有一个目录,存放打开的文件描述符号,

 

        3.每个程序默认打开三个文件设备:
                0:标准输入
                1:标准输出
                2:错误输出
        4.操作文件描述符号
                ssize_t write(int fd,
                    void *buf,//要写入内核对象的数据
                    size_t size);//写入数据大小
                返回:
                        >0 实际写入的数据
                        -1 写入错误    
                ssize_t read(int fd,
                        void *buf,//返回数据的空间
                        size_t size);//空间大小
                返回:
                        >0:实际读取的数据
                        =0:碰到文件结束符号EOF (ctrl+d)
                        -1:读取错误

 fd.c

#include <stdlib.h>
#include <stdio.h>
main()
{
	//printf("%d\n",getpid());
	//while(1);
	/*
	int r=write(0,"Hello\n",6);
	write(1,"world\n",6);
	write(2,"louis\n",6);
	int a=97;
	
	write(1,&a,4);//输出a 以字符输出
	*/
	char buf[32];
	//memset(buf,0,32);
	bzero(buf,32);
	
	int r=read(0,buf,30);
	printf("实际输入:%d\n",r);
	if(r>0)
	{
		buf[r]=0;
		printf("::%s\n",buf);
	}
	if(r==0)
	{
		printf("ctrl+d\n");
	}
	if(r==-1)
	{
		printf("输入错误!\n");
	}
		
	
}            

                建议:
                        0:输入
                        1:输出
                        2:错误输出                                  
                        
三.基于文件的描述符号
        1.得到文件描述符号/释放文件描述符号
            a.文件类型
                目录文件d
                普通文件f
                字符设备文件c
                块设备文件b(对应我们的存储设备 像硬盘)
                软连接文件l(类似快捷方式 硬连接文件相当于文件别名)
                管道文件p
                socket文件s            
            b.文件的属性
                    1.属性的表达方式:绝对模式,字符模式
                            0  0            0                0
                            拥有者      组      其他用户
                            0666
                    2.文件的权限属性:
                            读
                            写
                            执行
                            粘附位权限
                            用户设置位权限
                            组设置位权限
                        0   0                     0      0       0
                             特殊权限            Owner     group  其他用户
                    
                            s:
                            S
                            t
                            T
                        2.1.  s设置位
                                        2:组设置位
                                        4:用户设置位
                                    s对执行有效
                                    无效的设置位使用S表示
                                    
                                    设置位向其他用户开放拥有者权限的权限.用户设置位
                                    设置位向其他用户开放组用户权限的权限.组用户设置位
                                    设置位只对执行程序有意义(执行权限有意义)
                                    
                        2.2.  t设置位
                                        1:表示沾附位设置
                                     t对写文件有意义
                                    没有执行权限的沾附位使用T表示.
                                    沾附的目的:防止有些权限的用户删除文件.
                        
                        程序在执行的时候到底拥有的是执行者用户的权限
                        还是文件拥有者的权限.
                            程序执行中有两个用户:
                                        实际用户
                                        有效用户                        
            总结:
                    沾附位的作用:    防止其他有写权限用户删除文件
                    设置位的作用: 向其他执行者开发组或者用户的权限.
练习:
        1.使用cat创建一个文件
        2.设置沾附位,并观察属性
        3.设置用户设置位,    并观察属性
        4.设置组设置位,    并观察属性
        5.考虑w权限与沾附位的关系
        6.考虑x权限与设置位的关系.
                        
                                                         
        2.通过文件描述符号读写各种数据.                        
                open函数与creat函数
                int open(
                    const char *filename,//文件名
                    int flags,//open的方式[创建/打开]
                    mode_t mode//权限(只有创建的时候有效)
                    )
                    
                返回:
                        >=0:内核文件描述符号.
                        =-1:打开/创建失败
        
                open的方式:
                        必选方式:O_RDONLY O_WRONLY O_RDWR,必须选择一个
                        创建/打开:O_CREAT
                        可选方式:
                                        对打开可选方式:O_APPEND  O_TRUNC(清空数据)
                                        对创建可选方式:O_EXCL
                    组合:
                                创建:
                                        O_RDWR|O_CREAT
                                        O_RDWR|O_CREAT | O_EXCL    
                                
                                打开:                                        
                                        O_RDWR
                                        O_RDWR|O_APPEND
                                        O_RDWR|O_TRUNC
                    权限:
                            建议使用8进制数
                关闭

                void  close(int fd);
                                      


案例1:
        创建文件
案例2:
        创建文件并写入数据
                20        short float
                tom     20      99.99
                bush     70      65.00
                达内  40      100.00
        注意:
                文件的创建的权限受系统的权限屏蔽的影响
                umask             //显示屏蔽权限.
                umask 0666     //设置权限屏蔽.        
                

                ulimit -a 显示所有的其他限制.

open.c

/*创建文件*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main()
{
	int fd;
	
	char name[20];
	short age;
	float score;
	char sex;
	
	fd=open("test.dat",
		O_RDWR|O_CREAT|O_EXCL,
		00666);
	if(fd==-1) printf("open error:%m\n"),exit(-1);
	
	
	//写第一条
	memcpy(name,"tom",strlen("tom")+1);
	age=20;
	score=99.99;
	sex='F';
	
	write(fd,name,sizeof(name));
	write(fd,&age,sizeof age);
	write(fd,&score,sizeof(float));
	write(fd,&sex,sizeof(sex));
	
	//写第二条
	memcpy(name,"Bush",strlen("Bush")+1);
	age=70;
	score=65.00;
	sex='M';
	write(fd,name,sizeof(name));
	write(fd,&age,sizeof age);
	write(fd,&score,sizeof(float));
	write(fd,&sex,sizeof(sex));
	
	//写第三条
	
	memcpy(name,"达内",strlen("达内")+1);
	age=10;
	score=99.00;
	sex='F';
	write(fd,name,sizeof(name));
	write(fd,&age,sizeof age);
	write(fd,&score,sizeof(float));
	write(fd,&sex,sizeof(sex));
		
	close(fd);
}

案例3:
        打开文件读取数据
        重点:
                怎么打开读取
                文件尾的判定
        

        基本类型的数据读写.

read.c

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

main()
{
	char name[20];
	short age;
	float score;
	char sex;
	int fd;
	int r;
	fd=open("test.dat",O_RDONLY);
	if(fd==-1) printf("open error:%m\n"),exit(-1);
	
	while(1)
	{
		r=read(fd,name,sizeof(name));
		if(r==0) break;
		r=read(fd,&age,sizeof(short));
		r=read(fd,&score,sizeof(float));
		r=read(fd,&sex,sizeof(sex));
		printf("%s,\t%4hd,\t%.2f,\t%1c\n",
				name,age,score,sex);
	}
	
	close(fd);
	
}

        
案例4:
        结构体读取
        描述:从键盘读取若干条数据,保存到文件
                    数据追加

demo1.c

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
struct stu
{
	int no;
	char name[20];
	float score;
};
/*
1.判定文件是否存在,存在打开,不存在创建
2.输入记录
3.保存记录
4.提示继续输入
5.继续/不继续
6.关闭文件
*/
int openfile(const char *filename)
{
	int fd;
	fd=open(filename,O_RDWR|O_CREAT|O_EXCL,0666);
	if(fd==-1)//表示文件存在,则打开
	{
		fd=open(filename,O_RDWR|O_APPEND);
		return fd;
	}
	return fd;
}
void input(struct stu *record)
{
	bzero(record,sizeof(struct stu));
	printf("输入学号:");
	scanf("%d",&(record->no));
	printf("输入姓名:");
	scanf("%s",record->name);
	printf("输入成绩:");
	scanf("%f",&(record->score));
}
void save(int fd,struct stu *record)
{
	write(fd,record,sizeof(struct stu));//写完后地址自动改变
}
int iscontinue()
{
	char c;
	printf("是否继续输入:\n");
	//fflush(stdin);
	//fflush(stdout);
	scanf("\n%c",&c);	
	if(c=='Y' || c=='y')
	{
		return 1;
	}
	return 0;
}

int main()
{
	int fd;
	int r;
	struct stu s={0};
	fd=openfile("stu.dat");
	if(fd==-1) printf("openfile:%m\n"),exit(-1);
	
	while(1)
	{
		input(&s);
		save(fd,&s);
		r=iscontinue();
		if(r==0) break;
		system("clear");
	}
	close(fd);
	printf("输入完毕!\n");	
}

                      

                
                                                                                            
        3.文件描述符号与重定向
                    1.判定文件描述符号与终端的邦定关系
                    int isatty(int fd)
                    返回  非0:fd输出终端
                                 0:fd输出被重定向
                    2.防止重定向

                            /dev/tty

redir.c

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

int main()
{
	int fd;
	printf("Hello\n");
	write(1,"World\n",6);
	fd=open("/dev/tty",O_WRONLY);
	if(isatty(1))
	{
		write(1,"notredir\n",9);
	}
	else
	{
		write(1,"redir\n",6);
	}
	write(fd,"Killer\n",7);
}

          

总结:
        1.make的多目标依赖规则以及伪目标
        2.文件的创建与打开(了解设置位的作用)
        3.文件的读写(字符串/基本类型/结构体)
        4.了解描述符号与重定向

作业:
        1.完成上课的练习.
        2.写一个程序使用结构体读取1种的数据,
                    并全部打印数据,
                    并打印平均成绩
        3.写一个程序:
                查询1种的数据.比如:输入姓名,查询成绩
        4.写一个程序,录入保存如下数据:
                书名  出版社  价格  存储量  作者        
        5.写一个程序负责文件拷贝
                main 存在的文件  新的文件名
                要求:
                        文件存在就拷贝,不存在提示错误.
            
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值