一.IO與文件目錄管理 1.pread=lseek+read pread讀取以后不改變讀寫位置 2.mmap映射: /proc/${pid}/mem 無法映射 3.IO的有效用戶與實際用戶 默認(rèn)情況:實際用戶與有效用戶一致。 實際用戶:執(zhí)行用戶 有效用戶:權(quán)限用戶 uid_t getuid() uid_t geteuid()
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
main()
{
int fd;
char buf[1025];
int r;
printf("real user:%d\n",getuid());
printf("effective user:%d\n",geteuid());
fd=open("../day05",O_RDWR);
if(fd==-1) printf("open error:%m\n"),exit(-1);
bzero(buf,1024);
while((r=read(fd,buf,1024))>0)
{
buf[r]=0;
printf("%s",buf);
}
close(fd);
}
4.目錄相關(guān)函數(shù)
chdir 切換目錄
mkdir 創(chuàng)建目錄
rmdir 刪除目錄
unlink 刪除文件
umask 設(shè)置文件權(quán)限屏蔽位
stat 文件目錄狀態(tài)
5.目錄的遍歷
opendir系列函數(shù)
readdir
closedir
seekdir
dirfd
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
main()
{
DIR *d;
struct dirent *de;
//打開目錄
d=opendir("/home");
if(d==NULL)
{
printf("opendir:%m\n");
exit(-1);
}
//循環(huán)讀取目錄
while(de=readdir(d))
{
printf("%s,\t%d\n",de->d_name,de->d_type);
}
//關(guān)閉目錄
closedir(d);
}
int scandir(const char*dirname,//目錄名
struct dirent***namelist,//返回目錄列表
int (*)(struct dirent*),//回調(diào)函數(shù),過濾目錄
//NULL:不過濾
int (*)(struct dirent*,struct dirent*)//排序返回目錄
//NULL:不排序
);
返回: >=0 目錄個數(shù) =-1 目錄查找失敗
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
int mysort(const void*d1,const void*d2)
{
return -alphasort(d1,d2);
}
int myfilter(const struct dirent*d)
{
if(memcmp(d->d_name,".",1)==0)
{
return 0;
}
else
{
return -1;
}
}
main()
{
struct dirent**d;
int r;
int i;
r=scandir("/home",&d,myfilter,mysort);
printf("子目錄個數(shù):%d\n",r);
for(i=0;i<r;i++)
{
printf("%s\n",d[i]->d_name);
}
/*
while(*d)
{
printf("%s\n",(*d)->d_name);
d++;
}
*/
}
二.進(jìn)程 1.什么是進(jìn)程 執(zhí)行的程序:代碼->資源->CPU 進(jìn)程有很多數(shù)據(jù)維護(hù):進(jìn)程狀態(tài)/進(jìn)程的屬性 所有進(jìn)程屬性采用的結(jié)構(gòu)體維護(hù)->樹形數(shù)據(jù)結(jié)構(gòu) ps 察看進(jìn)程常見屬性 top 察看系統(tǒng)進(jìn)程執(zhí)行狀況 pstree(ptree) kill 向進(jìn)程發(fā)送信號 kill -s 信號 進(jìn)程id kill -l 顯示進(jìn)程能接受的所有信號 知道進(jìn)程有很多屬性:ps可以察看的屬性 2.創(chuàng)建進(jìn)程 1.代碼?加載到內(nèi)存?分配CPU時間片? 代碼由獨(dú)立的程序存在. 2.進(jìn)程有關(guān)的創(chuàng)建函數(shù) int system(const char*filename); 建立獨(dú)立進(jìn)程,擁有獨(dú)立的代碼空間,內(nèi)存空間 等待新的進(jìn)程執(zhí)行完畢,system才返回.(阻塞)案例: 使用system調(diào)用一個程序。 觀察進(jìn)程ID。 觀察阻塞。 新的返回值與system返回值有關(guān)系。 任何進(jìn)程的返回值:不要超過255。一個字節(jié)。 system的返回值中8-15位存放返回碼練習(xí): 使用system調(diào)用"ls -l"。"ls -l home"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
main()
{
int r;
printf("%d\n",getpid());
r=system("ls -l ");
//printf("%d\n",r>>8&255);
printf("%d\n",WEXITSTATUS(r));
system("clear");
}
子進(jìn)程:被創(chuàng)建進(jìn)程。 父進(jìn)程:相對被創(chuàng)建者的進(jìn)程。 popen:創(chuàng)建子進(jìn)程 在父子進(jìn)程之間建立一個管道案例: 使用popen調(diào)用ls -l,并且建立一個管道讀取輸出
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
main()
{
char buf[1024];
FILE *f=popen("ls -l","r");
int fd=fileno(f);
int r;
printf("=============\n");
while((r=read(fd,buf,1024))>0)
{
buf[r]=0;
printf("::%s\n",buf);
}
printf("=============\n");
close(fd);
pclose(f);
}
exec系列函數(shù): execl execlp 替換當(dāng)前進(jìn)程的代碼空間中的代碼數(shù)據(jù) 函數(shù)本身不創(chuàng)建新的進(jìn)程。 int execl(const char*path,const char *arg,....); 第一個參數(shù):替換的程序, 第二個參數(shù)....:命令行 命令行格式:命令名 選項參數(shù) 命令行結(jié)尾必須空字符串結(jié)尾案例: 使用exec執(zhí)行一個程序。 體會:*是否創(chuàng)建新的進(jìn)程?沒有 *體會execl的參數(shù)的命令行的格式 *體會execl與execlp的區(qū)別(execl只當(dāng)前路徑) execlp 使用系統(tǒng)的搜索路徑 *體會execl替換當(dāng)前進(jìn)程的代碼
#include <stdio.h>
#include <unistd.h>
int main()
{
//printf("main:%d\n",getpid());
int r=execlp("ls","ls","-l",NULL);
printf("結(jié)束%d\n",r);
return 0;
}
fork pid_t fork(); //1.創(chuàng)建進(jìn)程 //2.新進(jìn)程的代碼是什么:克隆父進(jìn)程的代碼 而且克隆了執(zhí)行的位置. //3.在子進(jìn)程不調(diào)用fork所以返回值=0; //4.父子進(jìn)程同時執(zhí)行.#include <stdio.h>
#include <unistd.h>
int main()
{
int pid;
printf("創(chuàng)建進(jìn)程前!\n");
pid=fork();
if(pid==0)
{
while(1)
{
printf("子進(jìn)程\n");
sleep(1);
}
}
else
{
while(1)
{
printf("父進(jìn)程\n");
sleep(1);
}
}
return 0;
}
3.應(yīng)用進(jìn)程 使用fork創(chuàng)建新的進(jìn)程有什么應(yīng)用價值呢? 使用fork實現(xiàn)多任務(wù).(Unix系統(tǒng)本身是不支持線程) 1.進(jìn)程 2.線程 3.信號 4.異步 5.進(jìn)程池與線程池案例: 使用進(jìn)程創(chuàng)建實現(xiàn)多任務(wù) 1.UI 2.建立多任務(wù)框架 3.分別處理不同的任務(wù)
#include <curses.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
WINDOW *wtime,*wnumb;
main()
{
initscr();
wtime=derwin(stdscr,3,10,0,(COLS-10));
wnumb=derwin(stdscr,3,11,(LINES-3)/2,(COLS-11)/2);
box(wtime,0,0);
box(wnumb,0,0);
refresh();
wrefresh(wtime);
wrefresh(wnumb);
if(fork())
{//show time
time_t tt;
struct tm *t;
while(1)
{
time(&tt);
t=localtime(&tt);
mvwprintw(wtime,1,1,"%02d:%02d:%02d",
t->tm_hour,t->tm_min,t->tm_sec);
refresh();
wrefresh(wtime);
wrefresh(wnumb);
sleep(1);
}
}
else
{//show number
int num=0;
int i;
while(1)
{
num=0;
for(i=0;i<7;i++)
{
num=num*10+rand()%10;
}
mvwprintw(wnumb,1,2,"%07d",num);
refresh();
wrefresh(wtime);
wrefresh(wnumb);
usleep(10000);
}
}
endwin();
}
4.理解進(jìn)程 1.父子進(jìn)程的關(guān)系 獨(dú)立的兩個進(jìn)程 互為父子關(guān)系 2.問題: 2.1.父進(jìn)程先結(jié)束? 子進(jìn)程就依托根進(jìn)程init:孤兒進(jìn)程 孤兒進(jìn)程沒有任何危害. 2.2.子進(jìn)程先結(jié)束? 子進(jìn)程會成為僵死進(jìn)程. 僵死進(jìn)程不占用內(nèi)存,CPU.但在進(jìn)程任務(wù)管理樹占用一個節(jié)點. 僵死進(jìn)程造成進(jìn)程名額資源浪費(fèi). 所以處理僵死進(jìn)程. 3.僵死進(jìn)程使用wait回收 4.父進(jìn)程怎么知道子進(jìn)程退出? 子進(jìn)程結(jié)束通常會向父進(jìn)程發(fā)送一個信號 SIGCHLD 5.父進(jìn)程處理子進(jìn)程退出信號 signal(int sig,void(*fun)(int)); 向系統(tǒng)注冊:只要sig信號發(fā)生,系統(tǒng)停止進(jìn)程,并調(diào)用函數(shù)fun 當(dāng)函數(shù)執(zhí)行完畢,繼續(xù)原來進(jìn)程 5.1.實現(xiàn)處理函數(shù) 5.2.使用signal邦定信號與函數(shù) 僵死進(jìn)程回收案例:#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
void deal(
int s)
{
int status;
wait(&status);
printf("回收中

..\n");
sleep(5);
printf("回收完畢:%d!\n",WEXITSTATUS(status));
}
main()
{
if(fork()==0)
{
//child
printf("child!\n");
sleep(20);
printf("退出!\n");
exit(88);
}
else {
//parent
signal(17,deal);
while(1)
{
printf("parent!\n");
sleep(1);
}
//sleep(20000); 這里父進(jìn)程也會被sigchld信號喚醒,在執(zhí)行完信號處理程序后,繼續(xù)向下執(zhí)行 printf("parent!\n");
}
}
6.父子進(jìn)程的資源訪問 6.1.內(nèi)存資源
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/mman.h>
main()
{
/*
int *a=mmap(0,4,PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE,0,0);
*/
int *a=sbrk(4);
*a=40;
if(fork())
{
printf("parent:%d\n",*a);
*a=90;
}
else
{
printf("child:%d\n",*a);
sleep(3);
printf("child:%d\n",*a);
}
}
6.2.文件資源
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/mman.h>
#include <fcntl.h>
main()
{
if(fork())
{
int fd=open("test.txt",O_RDWR);
printf("%d\n",fd);
sleep(5);
write(fd,"Killer",6);
close(fd);
}
else
{
int fd=open("test.txt",O_RDWR);
printf("%d\n",fd);
write(fd,"Clinton",7);
sleep(8);
close(fd);
}
}
案例:
說明:子進(jìn)程克隆整個內(nèi)存區(qū)域,
但內(nèi)存區(qū)域指向不同的物理空間
盡管克隆,但內(nèi)存獨(dú)立. 不能相互訪問.
多進(jìn)程實現(xiàn)多任務(wù),進(jìn)程之間的數(shù)據(jù)交換是大問題.(IPC)
Inter-Process Commucation
映射內(nèi)存:
MAP_SHARED:映射到同一物理內(nèi)存
MAP_PRIVATE:映射到不同的物理內(nèi)存.
案例:
兩個進(jìn)程之間,文件描述符號指向的是同一個文件內(nèi)核對象.
回顧:
1.目錄遍歷
2.進(jìn)程創(chuàng)建system popen exec fork
3.僵死進(jìn)程出現(xiàn)的條件以及回收
4.利用多進(jìn)程實現(xiàn)簡單的多任務(wù)
5.理解進(jìn)程的克隆.
作業(yè):
1.使用兩個進(jìn)程,查找素數(shù):(多任務(wù))
A進(jìn)程查找1-5000
B進(jìn)程查找5001-10000
把素數(shù)寫入文件.
2.寫一個多任務(wù):(兩個進(jìn)程數(shù)據(jù)共享)
A.進(jìn)程查找素數(shù),放入mmap分配的空間
B.進(jìn)程把mmap的數(shù)據(jù)取出來,判定兩個數(shù)據(jù)是否相鄰.
相鄰就打印這兩個素數(shù).
思考:
3.使用opendir/readir遍歷指定目錄下的所有*.c文件.
scandir
明天:
一.進(jìn)程的基本控制
二.進(jìn)程的高級控制-信號