一、make與makefile
1.回顧:
目標(biāo)的語(yǔ)法
目標(biāo)名:依賴目標(biāo)
@命令
@命令
make的命令行使用
make -f make腳本文件 目標(biāo)名
2.目標(biāo)的劃分
目標(biāo)依賴
3.默認(rèn)規(guī)則:
a.不指定目標(biāo),執(zhí)行第一個(gè)目標(biāo)
b.不指定make文件,默認(rèn)文件是makefile Makefile
makefile優(yōu)先
4.目標(biāo)的調(diào)用規(guī)則:(make把目標(biāo)當(dāng)成當(dāng)前文件夾下同名的文件)
make執(zhí)行目標(biāo):
搜索與目標(biāo)相同的文件
如果文件存在,則判定文件是否被修改過(guò)。
文件未被修改,則停止執(zhí)行,輸出提示
文件修改過(guò),則進(jìn)行執(zhí)行。(文件不存在屬于被修改過(guò)范疇)
比較:當(dāng)前目標(biāo)與依賴目標(biāo)
5.建議:
只要有文件輸出,就把任務(wù)作為一個(gè)目標(biāo),并且把輸出的文件作為目標(biāo)名。
范例:
input.o:input.c
gcc -c -fpic input.c
libdemo.so:input.o
gcc -shared -olibdemo.so input.o
demo:libdemo.so demo.c
gcc demo.c -ldemo -L. -odemo
6.潛規(guī)則(不建議)
適用于:.c目標(biāo)與.o目標(biāo)。
查找.o目標(biāo),目標(biāo)不存在,就把.o替換成.c
如果.c存在,實(shí)施潛規(guī)則:直接調(diào)用gcc把.c執(zhí)為.o
7.變量
變量名=值 值
$(變量名) ${變量}
8.偽目標(biāo):
不把目標(biāo)作為文件處理的目標(biāo)稱為偽目標(biāo)
聲明偽目標(biāo)
.PHONY=目標(biāo)
二、環(huán)境變量
1.使用main的參數(shù)
int main(int args,char *argv[],char **arge)
{
}
命令行參數(shù)argv與環(huán)境行arge都是字符串?dāng)?shù)組.
約定:最后一個(gè)字符串是NULL/0
2.在C的標(biāo)準(zhǔn)庫(kù)提供:外部變量
extern char **environ;
#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++;
}
}
3.修改獲取某個(gè)環(huán)境變量 getenv/setenv/unsetenv
#include <stdlib.h>
#include <stdio.h>
main()
{
char *val;
val=getenv("PATH");
printf("%s\n",val);
}
三、IO的基礎(chǔ) 1.認(rèn)識(shí)內(nèi)核對(duì)象 不允許訪問(wèn)內(nèi)核設(shè)備和內(nèi)存,但可以通過(guò)內(nèi)核系統(tǒng)函數(shù)去訪問(wèn). 對(duì)每個(gè)內(nèi)核對(duì)象進(jìn)行編號(hào)ID. 如果訪問(wèn)內(nèi)核對(duì)象,只能通過(guò)ID. 編程模型: 申請(qǐng)得到一個(gè)ID 在內(nèi)核系統(tǒng)函數(shù)中使用ID得到對(duì)應(yīng)內(nèi)核對(duì)象數(shù)據(jù) 2.怎么訪問(wèn)文件 使用函數(shù),傳遞一個(gè)文件,系統(tǒng)打開(kāi)文件,加載文件數(shù)據(jù), 返回一個(gè)ID. 使用函數(shù),傳遞ID,得到數(shù)據(jù). 使用函數(shù)傳遞ID,告訴系統(tǒng)釋放文件. ID:文件描述符號(hào).file description (fd) 每個(gè)程序執(zhí)行的時(shí)候都有一個(gè)目錄,存放打開(kāi)的文件描述符號(hào) 3.每個(gè)程序默認(rèn)打開(kāi)三個(gè)文件設(shè)備: 0:標(biāo)準(zhǔn)輸入 1:標(biāo)準(zhǔn)輸出 2:錯(cuò)誤輸出 4.操作文件描述符號(hào) ssize_t write(int fd, void *buf,//要寫(xiě)入內(nèi)核對(duì)象的數(shù)據(jù) size_t size);//寫(xiě)入數(shù)據(jù)大小 返回: >0 實(shí)際寫(xiě)入的數(shù)據(jù) -1 寫(xiě)入錯(cuò)誤 ssize_t read(int fd, void *buf,//返回?cái)?shù)據(jù)的空間 size_t size);//空間大小 返回: >0:實(shí)際讀取的數(shù)據(jù) =0:碰到文件結(jié)束符號(hào)EOF (ctrl+d) -1:讀取錯(cuò)誤 建議: 0:輸入 1:輸出 2:錯(cuò)誤輸出課堂練習(xí): 1.使用write向0 1 2 寫(xiě)數(shù)據(jù) 2.使用read從0 1 讀取數(shù)據(jù),并判定輸入的情況,然后根據(jù)相應(yīng)的結(jié)果輸出提示
#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=20;
write(1,&a,4);
*/
char buf[32];
//memset(buf,0,32);
bzero(buf,32);
int r=read(0,buf,30);
printf("實(shí)際輸入:%d\n",r);
if(r>0)
{
buf[r]=0;
printf("::%s\n",buf);
}
if(r==0)
{
printf("ctrl+d\n");
}
if(r==-1)
{
printf("輸入錯(cuò)誤!\n");
}
}
三.基于文件的描述符號(hào)
1.得到文件描述符號(hào)/釋放文件描述符號(hào)
a.文件類型
目錄文件d
普通文件f
字符設(shè)備文件c
塊設(shè)備文件b
軟連接文件l
管道文件p
socket文件s
b.文件的屬性
1.屬性的表達(dá)方式:絕對(duì)模式(0666類似的八進(jìn)制數(shù)),字符模式(rwx)
0 0 0 0
擁有者 組 其他用戶
0666
2.文件的權(quán)限屬性:
讀
寫(xiě)
執(zhí)行
粘附位權(quán)限
用戶設(shè)置位權(quán)限
組設(shè)置位權(quán)限
0 0 0 0 0
特殊權(quán)限 Owner group 其他用戶
s:
S
t
T
2.1. s設(shè)置位
2:組設(shè)置位
4:用戶設(shè)置位
s對(duì)執(zhí)行有效
無(wú)效的設(shè)置位使用S表示
設(shè)置位向其他用戶開(kāi)放擁有者權(quán)限的權(quán)限.用戶設(shè)置位
設(shè)置位向其他用戶開(kāi)放組用戶權(quán)限的權(quán)限.組用戶設(shè)置位
設(shè)置位只對(duì)執(zhí)行程序有意義(執(zhí)行權(quán)限有意義)
2.2. t設(shè)置位
1:表示沾附位設(shè)置
t對(duì)寫(xiě)文件有意義
沒(méi)有執(zhí)行權(quán)限的沾附位使用T表示.
沾附的目的:防止有些權(quán)限的用戶刪除文件.
程序在執(zhí)行的時(shí)候到底擁有的是執(zhí)行者用戶的權(quán)限
還是文件擁有者的權(quán)限.(看setUID)
程序執(zhí)行中有兩個(gè)用戶:
實(shí)際用戶:標(biāo)示進(jìn)程到底是誰(shuí)
有效用戶:標(biāo)示進(jìn)程訪問(wèn)資源的權(quán)限
上述一般情況是一樣的,有時(shí)候被setUID改變
總結(jié):
沾附位的作用: 防止其他有寫(xiě)權(quán)限用戶刪除文件
設(shè)置位的作用: 向其他執(zhí)行者開(kāi)發(fā)組或者用戶的權(quán)限.
練習(xí):
1.使用cat創(chuàng)建一個(gè)文件
2.設(shè)置沾附位,并觀察屬性
3.設(shè)置用戶設(shè)置位, 并觀察屬性
4.設(shè)置組設(shè)置位, 并觀察屬性
5.考慮w權(quán)限與沾附位的關(guān)系
6.考慮x權(quán)限與設(shè)置位的關(guān)系.
2.通過(guò)文件描述符號(hào)讀寫(xiě)各種數(shù)據(jù).
open函數(shù)與creat函數(shù)
int open(
const char *filename,//文件名
int flags,//open的方式[創(chuàng)建/打開(kāi)]
mode_t mode//權(quán)限(只有創(chuàng)建的時(shí)候有效)
)
返回:
>=0:內(nèi)核文件描述符號(hào).
=-1:打開(kāi)/創(chuàng)建失敗
open的方式:
必選方式:O_RDONLY O_WRONLY O_RDWR,必須選擇一個(gè)
創(chuàng)建/打開(kāi):O_CREAT
可選方式:
對(duì)打開(kāi)可選方式:O_APPEND O_TRUNC(清空數(shù)據(jù))
對(duì)創(chuàng)建可選方式:O_EXCL
組合:
創(chuàng)建:
O_RDWR|O_CREAT
O_RDWR|O_CREAT | O_EXCL
打開(kāi):
O_RDWR
O_RDWR|O_APPEND
O_RDWR|O_TRUNC
權(quán)限:
建議使用8進(jìn)制數(shù)
關(guān)閉
void close(int fd);
案例1:
創(chuàng)建文件
案例2:
創(chuàng)建文件并寫(xiě)入數(shù)據(jù)
20 short float
tom 20 99.99
bush 70 65.00
達(dá)內(nèi) 40 100.00
注意:
文件的創(chuàng)建的權(quán)限受系統(tǒng)的權(quán)限屏蔽的影響
umask //顯示屏蔽權(quán)限.
umask 0666 //設(shè)置權(quán)限屏蔽.
ulimit -a 顯示所有的其他限制.
/*創(chuàng)建文件*/
#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,
);
if(fd==-1) printf("open error:%m\n"),exit(-1);
//寫(xiě)第一條
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));
//寫(xiě)第二條
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));
//寫(xiě)第三條
memcpy(name,"達(dá)內(nèi)",strlen("達(dá)內(nèi)")+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: 打開(kāi)文件讀取數(shù)據(jù) 重點(diǎn): 怎么打開(kāi)讀取 文件尾的判定 基本類型的數(shù)據(jù)讀寫(xiě).
#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: 結(jié)構(gòu)體讀取 描述:從鍵盤(pán)讀取若干條數(shù)據(jù),保存到文件 數(shù)據(jù)追加View Code
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
struct stu
{
int no;
char name[20];
float score;
};
/*
.判定文件是否存在,存在打開(kāi),不存在創(chuàng)建
.輸入記錄
.保存記錄
.提示繼續(xù)輸入
.繼續(xù)/不繼續(xù)
.關(guān)閉文件
*/
int openfile(const char *filename)
{
int fd;
fd=open(filename,O_RDWR|O_CREAT|O_EXCL,0666);
if(fd==-1)//表示文件存在,則打開(kāi)
{
fd=open(filename,O_RDWR|O_APPEND);
return fd;
}
return fd;
}
void input(struct stu *record)
{
bzero(record,sizeof(struct stu));
printf("輸入學(xué)號(hào):");
scanf("%d",&(record->no));
printf("輸入姓名:");
scanf("%s",record->name);
printf("輸入成績(jī):");
scanf("%f",&(record->score));
}
void save(int fd,struct stu *record)
{
write(fd,record,sizeof(struct stu));
}
int iscontinue()
{
char c;
printf("是否繼續(xù)輸入:\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.文件描述符號(hào)與重定向 1.判定文件描述符號(hào)與終端的邦定關(guān)系 int isatty(int fd) 返回非0:fd輸出終端 0:fd輸出被重定向 2.防止重定向 /dev/tty
#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);
}
總結(jié):
1.make的多目標(biāo)依賴規(guī)則以及偽目標(biāo)
2.文件的創(chuàng)建與打開(kāi)(了解設(shè)置位的作用)
3.文件的讀寫(xiě)(字符串/基本類型/結(jié)構(gòu)體)
4.了解描述符號(hào)與重定向
作業(yè):
1.完成上課的練習(xí).
2.寫(xiě)一個(gè)程序使用結(jié)構(gòu)體讀取1種的數(shù)據(jù),
并全部打印數(shù)據(jù),
并打印平均成績(jī)
3.寫(xiě)一個(gè)程序:
查詢1種的數(shù)據(jù).比如:輸入姓名,查詢成績(jī)
4.寫(xiě)一個(gè)程序,錄入保存如下數(shù)據(jù):
書(shū)名 出版社 價(jià)格 存儲(chǔ)量 作者
5.寫(xiě)一個(gè)程序負(fù)責(zé)文件拷貝
main 存在的文件 新的文件名
要求:
文件存在就拷貝,不存在提示錯(cuò)誤.