您的位置:首页 > 运维架构 > Linux

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

2014-09-06 16:33 337 查看

一、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 存在的文件 新的文件名

要求:

文件存在就拷贝,不存在提示错误.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: