一、make与makefile
1. 回顾:
目标的语法
目标名:依赖目标
@命令
@命令
make的命令行使用
make -f make脚本文件 目标名
2. 目标的划分
目标依赖
3. 默认规则:
3.1 不指定目标,执行第一个目标
3.2 不指定make文件,默认文件是
makefile(无拓展名) Makefile(无拓展名)
makefile优先
4. 目标的调用规则:(make把目标当作文件)
make执行目标:
搜索与目标相同的文件,如果文件存在,则判定日期:日期最新,则停止执行,输出提示;日期不是最新,则进行执行。
比较:当前目标与依赖目标
5. 建议:
只要有文件输出,就把任务作为一个目标,并且把输出的文件作为目标名。
6. 潜规则(尽量不要使用该规则)
存在于 .c目标与.o目标之间
首先查找.o目标,如果目标不存在,就把.o替换成.c
如果.c存在,实施潜规则:直接调用gcc把.c执为.o
7. 在makefile文件中定义变量
变量名可以大写也可以小写
变量名=值 值
$(变量名) ${变量}
8. 伪目标:
不把目标作为文件处理的目标称为伪目标
声明伪目标,这样不会比较文件日期,直接执行语句.
PHONY就是声明伪目标
9. 没有将的知识点:
1. make的配置
2. make的变量的操作函数
3. 多make文件使用
二、 环境变量
1. 使用main的参数
int main(int args,char *argv[],char **arge)
{
}
三个参数:命令个数,命令字符串,环境变量字符串
命令行参数argv与环境行arge都是字符串数组。
约定:最后一个字符串是NULL/0
环境变量的输出方法
#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
#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, //ID
void *buf, //要写入内核对象的数据
size_t size); //写入数据大小
返回:
>0:实际写入的数据
-1:写入错误
ssize_t read(
int fd, //ID
void *buf, //返回数据的空间
size_t size); //空间大小
返回:
>0:实际读取的数据
=0:碰到文件结束符号EOF (ctrl+d)
-1:读取错误
建议:
0:数据流输入
1:数据流输出
2:错误输出
#include <stdlib.h>
#include <stdio.h>
main()
{
//printf("%d\n",getpid());
//while(1);
/*
//下面这三个write写法不规范,应该按照0 输入 1输出 2错误的方式填写id号
int r=write(0,"Hello\n",6);
write(1,"world\n",6);
write(2,"louis\n",6);
//正确写法
int a=97;
write(1,&a,4);
*/
char buf[32];
//初始化内存为0
//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");
}
}
四、基于文件的描述符号
1. 得到/释放文件描述符号
1.1 文件类型:
目录文件 d
普通文件 f
字符设备文件 c
块设备文件 b
软连接文件 l
管道文件 p
socket文件 s
1.2 文件的属性
1.2.1 属性的表达方式:绝对模式(rwx)、字符模式(421)(对应读写执行)
上图:用户权限是分组控制的形式,三个组:拥有着权限、组权限、其他用户权限。
0 0 0 0 0
特殊权限 拥有者 组 其他用户
0 6 6 6
1.2.2 文件的权限属性:
读
写
执行
粘附位权限
用户设置位权限
组设置位权限
s、S、t、T。
1.2.2.1 s设置位
2:组设置位
4:用户设置位
s对执行有效,无效的设置位使用S表示
设置位向其他用户开放拥有者权限的权限.用户设置位
设置位向其他用户开放组用户权限的权限.组用户设置位
设置位只对执行程序有意义(执行权限有意义)
1.2.2.2 t设置位
1:表示沾附位设置
t对写文件有意义,没有执行权限的沾附位使用T表示。
沾附的目的:防止有些权限的用户删除文件。
程序在执行的时候到底拥有的是执行者用户的权限还是文件拥有者的权限?
程序执行中有两个用户:
实际用户:
有效用户:
总结:
沾附位的作用:防止其他有写权限用户删除文件
设置位的作用:向其他执行者开发组或者用户的权限.
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);
视频损坏,自己看代码吧
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);
}
demo.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");
}