一、make與makefile
1.回顧:
目標的語法
目標名:依賴目標
@命令
@命令
make的命令行使用
make -f make腳本文件 目標名
2.目標的劃分
目標依賴
3.默認規(guī)則:
a.不指定目標,執(zhí)行第一個目標
b.不指定make文件,默認文件是makefile Makefile
makefile優(yōu)先
4.目標的調用規(guī)則:(make把目標當成當前文件夾下同名的文件)
make執(zhí)行目標:
搜索與目標相同的文件
如果文件存在,則判定文件是否被修改過。
文件未被修改,則停止執(zhí)行,輸出提示
文件修改過,則進行執(zhí)行。(文件不存在屬于被修改過范疇)
比較:當前目標與依賴目標
5.建議:
只要有文件輸出,就把任務作為一個目標,并且把輸出的文件作為目標名。
范例:
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目標與.o目標。
查找.o目標,目標不存在,就把.o替換成.c
如果.c存在,實施潛規(guī)則:直接調用gcc把.c執(zhí)為.o
7.變量
變量名=值 值
$(變量名) ${變量}
8.偽目標:
不把目標作為文件處理的目標稱為偽目標
聲明偽目標
.PHONY=目標
二、環(huán)境變量
1.使用main的參數
int main(int args,char *argv[],char **arge)
{
}
命令行參數argv與環(huán)境行arge都是字符串數組.
約定:最后一個字符串是NULL/0
2.在C的標準庫提供:外部變量
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.修改獲取某個環(huán)境變量 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) 每個程序執(zhí)行的時候都有一個目錄,存放打開的文件描述符號 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:讀取錯誤 建議: 0:輸入 1:輸出 2:錯誤輸出課堂練習: 1.使用write向0 1 2 寫數據 2.使用read從0 1 讀取數據,并判定輸入的情況,然后根據相應的結果輸出提示
#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("實際輸入:%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.得到文件描述符號/釋放文件描述符號
a.文件類型
目錄文件d
普通文件f
字符設備文件c
塊設備文件b
軟連接文件l
管道文件p
socket文件s
b.文件的屬性
1.屬性的表達方式:絕對模式(0666類似的八進制數),字符模式(rwx)
0 0 0 0
擁有者 組 其他用戶
0666
2.文件的權限屬性:
讀
寫
執(zhí)行
粘附位權限
用戶設置位權限
組設置位權限
0 0 0 0 0
特殊權限 Owner group 其他用戶
s:
S
t
T
2.1. s設置位
2:組設置位
4:用戶設置位
s對執(zhí)行有效
無效的設置位使用S表示
設置位向其他用戶開放擁有者權限的權限.用戶設置位
設置位向其他用戶開放組用戶權限的權限.組用戶設置位
設置位只對執(zhí)行程序有意義(執(zhí)行權限有意義)
2.2. t設置位
1:表示沾附位設置
t對寫文件有意義
沒有執(zhí)行權限的沾附位使用T表示.
沾附的目的:防止有些權限的用戶刪除文件.
程序在執(zhí)行的時候到底擁有的是執(zhí)行者用戶的權限
還是文件擁有者的權限.(看setUID)
程序執(zhí)行中有兩個用戶:
實際用戶:標示進程到底是誰
有效用戶:標示進程訪問資源的權限
上述一般情況是一樣的,有時候被setUID改變
總結:
沾附位的作用: 防止其他有寫權限用戶刪除文件
設置位的作用: 向其他執(zhí)行者開發(fā)組或者用戶的權限.
練習:
1.使用cat創(chuàng)建一個文件
2.設置沾附位,并觀察屬性
3.設置用戶設置位, 并觀察屬性
4.設置組設置位, 并觀察屬性
5.考慮w權限與沾附位的關系
6.考慮x權限與設置位的關系.
2.通過文件描述符號讀寫各種數據.
open函數與creat函數
int open(
const char *filename,//文件名
int flags,//open的方式[創(chuàng)建/打開]
mode_t mode//權限(只有創(chuàng)建的時候有效)
)
返回:
>=0:內核文件描述符號.
=-1:打開/創(chuàng)建失敗
open的方式:
必選方式:O_RDONLY O_WRONLY O_RDWR,必須選擇一個
創(chuàng)建/打開:O_CREAT
可選方式:
對打開可選方式:O_APPEND O_TRUNC(清空數據)
對創(chuàng)建可選方式:O_EXCL
組合:
創(chuàng)建:
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:
創(chuàng)建文件
案例2:
創(chuàng)建文件并寫入數據
20 short float
tom 20 99.99
bush 70 65.00
達內 40 100.00
注意:
文件的創(chuàng)建的權限受系統的權限屏蔽的影響
umask //顯示屏蔽權限.
umask 0666 //設置權限屏蔽.
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);
//寫第一條
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: 打開文件讀取數據 重點: 怎么打開讀取 文件尾的判定 基本類型的數據讀寫.
#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: 結構體讀取 描述:從鍵盤讀取若干條數據,保存到文件 數據追加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;
};
/*
.判定文件是否存在,存在打開,不存在創(chuàng)建
.輸入記錄
.保存記錄
.提示繼續(xù)輸入
.繼續(xù)/不繼續(xù)
.關閉文件
*/
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("是否繼續(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.文件描述符號與重定向 1.判定文件描述符號與終端的邦定關系 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);
}
總結:
1.make的多目標依賴規(guī)則以及偽目標
2.文件的創(chuàng)建與打開(了解設置位的作用)
3.文件的讀寫(字符串/基本類型/結構體)
4.了解描述符號與重定向
作業(yè):
1.完成上課的練習.
2.寫一個程序使用結構體讀取1種的數據,
并全部打印數據,
并打印平均成績
3.寫一個程序:
查詢1種的數據.比如:輸入姓名,查詢成績
4.寫一個程序,錄入保存如下數據:
書名 出版社 價格 存儲量 作者
5.寫一個程序負責文件拷貝
main 存在的文件 新的文件名
要求:
文件存在就拷貝,不存在提示錯誤.