- 作業(yè):在文件任意位置處插入數(shù)據(jù)
#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h> //errno
#include <unistd.h> //write() read() sleep()
/*open()*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PER_IO_BYTES 4096
int main(int argc,char *argv[])
{
int fd=-1;
char caFile[32]={'\0'};//將原來文件保存再重命名
strncpy(caFile,argv[1],sizeof(caFile));//將test.data里面的內(nèi)容復(fù)制到caFile
int ret=-1;
strcat(caFile,".old");
ret=rename(argv[1],caFile);//將原來的文件重命名
if(-1==ret)
{
printf("rename error:%s\n",strerror(errno));//如果錯(cuò)誤,打印錯(cuò)誤信息
return -1;
}
int fdNew=-1;
fdNew=open(argv[1],O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);//寫打開,訪問權(quán)限
if(-1==fdNew)
{
printf("open error:%s\n",strerror(errno));
return -1;
}
int fdOld=-1;
fdOld=open(caFile,O_RDONLY);//讀打開原來的文件
if(-1==fdOld)
{
printf("open error:%s\n",strerror(errno));
return -1;
}
off_t offset=0;//定義偏移量為5
printf("please input position:");
scanf("%ld",&offset);
char caBuf[PER_IO_BYTES]={'\0'};//初始化
int iLeft=offset;
int iReaded=0;
while(iLeft)//將指定位置前面的數(shù)據(jù)讀出來
{
if(iLeft>=PER_IO_BYTES)
{
ret=read(fdOld,caBuf,PER_IO_BYTES);
}
else
{
ret=read(fdOld,caBuf,iLeft);
}
if(-1==ret)
{
printf("read error:%s\n",strerror(errno));
break;
}
iLeft-=ret;
ret=write(fdNew,caBuf,ret);
if(-1==ret)
{
printf("write error:%s\n",strerror(errno));
break;
}
}
//在制定的位置插入該數(shù)據(jù)
char *pData="$$$qqrhtewrywywruiepitrew$$$";
ret=write(fdNew,pData,strlen(pData));
if(-1==ret)
{
printf("write error:%s\n",strerror(errno));
return;
}
offset=lseek(fdOld,0,SEEK_CUR);
while(1)
{
ret=read(fdOld,caBuf,PER_IO_BYTES);
if(-1==ret)
{
printf("read error:%s\n",strerror(errno));
break;
}
else if(0==ret)
{
break;
}
ret=write(fdNew,caBuf,ret);
if(-1==ret)
{
printf("write error:%s\n",strerror(errno));
break;
}
}
close(fdNew);
close(fdOld);
ret=remove(caFile);
if(-1==ret)
{
printf("remove error:%s\n",strerror(errno));
return -1;
}
return 0;
}
//gcc lseek1.c
//./a.out test.data
//結(jié)果為:在第第四個(gè)位置插入數(shù)據(jù):
//1234$$$qqrhtewrywywruiepitrew$$$567890abcdefghijklmn
ACCESS(測試)
- 測試文件是否存在
#include<unistd.h>
#include<stdio.h>//perror
//mode:
// F_OK:測試文件是否存在
// R_OK:測試用戶是否對文件具有可讀權(quán)限
// W_OK:測試用戶是否對文件具有可寫權(quán)限
// X_OK:測試用戶是否對文件具有可執(zhí)行權(quán)限
//測試用戶對于指定的文件是否具有mode權(quán)限
//如果有,則函數(shù)返回0
//否則返回-1
//int access(const char *pathname, int mode);
int main(int argc,char *argv[])
{
int ret=-1;
ret=access(argv[1],F_OK);//測試文件是否存在
if(-1==ret)
{
perror("access");//如果錯(cuò)誤,則會(huì)打印access:錯(cuò)誤信息
return -1;
}
else if(0==ret)
{
printf("file exist\n");
}
return 0;
}
//./a.out test.data
- 測試文件是否有可讀可寫權(quán)限
#include<unistd.h>
#include<stdio.h>//perror
int main(int argc,char *argv[])
{
int ret=-1;
ret=access(argv[1],R_OK | W_OK);//測試文件是否有可讀可寫的權(quán)限
if(-1==ret)
{
perror("access");//如果錯(cuò)誤,則會(huì)打印access:錯(cuò)誤信息
return -1;
}
else if(0==ret)
{
printf("user has those permissions\n");
}
return 0;
}
//./a.out test.data
- 測試文件是否有可執(zhí)行權(quán)限
#include<unistd.h>
#include<stdio.h>//perror
int main(int argc,char *argv[])
{
int ret=-1;
ret=access(argv[1],X_OK);//測試文件是否有可讀可寫的權(quán)限
if(-1==ret)
{
perror("access");//如果錯(cuò)誤,則會(huì)打印access:錯(cuò)誤信息
return -1;
}
else if(0==ret)
{
printf("user has those permissions\n");
}
return 0;
}
OPENDIR(打開目錄)
- 打開一個(gè)文件目錄
#include <stdio.h>
#include <string.h> //strerror()
/*open()*/
#include <sys/types.h>
#include <dirent.h>
int main(int argc,char *argv[])
{
//打開指定的目錄,打開失敗返回NULL,成功則返回一個(gè)指向目錄的指針
DIR *pDIR=opendir(argv[1]);
if(NULL==pDIR)//打開失敗
{
perror("opendir");
return -1;
}
printf("opendir ok\n");
closedir(pDIR);
}
//打開成功:opendir ok
Paste_Image.png
- 打開文件目錄進(jìn)行遍歷目錄里面的內(nèi)容
#include <stdio.h>
#include <string.h> //strerror()
/*open()*/
#include <sys/types.h>
#include <dirent.h>
int main(int argc,char *argv[])
{
//打開指定的目錄,打開失敗返回NULL,成功則返回一個(gè)指向目錄的指針
DIR *pDIR=opendir(argv[1]);
if(NULL==pDIR)//打開失敗
{
perror("opendir:");
return -1;
}
printf("opendir ok\n");
struct dirent *pDirent=NULL;
pDirent=readdir(pDIR);//獲得一個(gè)文件信息。遍歷一個(gè)目錄里的文件
while(NULL !=pDirent)//繼續(xù)讀(可能有好多目錄)
{
printf("%s ",pDirent->d_name);
pDirent=readdir(pDIR);
}
printf("\n");
closedir(pDIR);
}
//./a.out 1
//./a.out ../上午
//./a.out ../../11.30
Paste_Image.png
- 遍歷目錄內(nèi)容,判斷是普通文件還是目錄文件還是其他類型
#include <stdio.h>
#include <string.h>
/*stat()*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/*opendir()*/
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char *argv[])
{
//打開指定的目錄,打開失敗返回NULL,并設(shè)置錯(cuò)誤號(hào)
//成功返回一個(gè)指向目錄的指針
DIR *pDir = opendir(argv[1]);
if (NULL == pDir)
{
perror("opendir:");
return -1;
}
printf("opendir ok\n");
struct dirent *pDirent = NULL;
struct stat fileStat;
int ret = -1;
pDirent = readdir(pDir);
while (NULL != pDirent)
{
printf("%s ", pDirent->d_name);
ret = stat(pDirent->d_name, &fileStat);
if (0 == ret)
{
switch (fileStat.st_mode & S_IFMT)
{
case S_IFREG:
printf("這是一個(gè)普通的文件\n");
break;
case S_IFDIR:
printf("這是一個(gè)目錄的文件\n");
break;
default:
printf("其他類型的文件\n");
break;
}
}
else if (-1 == ret)
{
perror("stat");
break;
}
pDirent = readdir(pDir);
}
printf("\n");
//返回到目錄的頭部
//rewinddir(pDirent);
//創(chuàng)建一個(gè)目錄
//mkdir(pathname, mode);
//刪除一個(gè)目錄
//rmdir(pDrient);
closedir(pDir);
return 0;
}
//./a.out 1
//./a.out ../上午
Paste_Image.png
- 求一個(gè)文件的普通文件的個(gè)數(shù),目錄文件的個(gè)數(shù),其他類型文件的個(gè)數(shù)
#include <stdio.h>
#include <string.h>
/*stat()*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/*opendir()*/
#include <sys/types.h>
#include <dirent.h>
int main(int argc,char *argv[])
{
DIR *pDir=opendir(argv[1]);
if(NULL==pDir)
{
perror("opendir");
return -1;
}
printf("opendir ok\n");
struct dirent *pDirent=NULL;
struct stat fileStat;
int ret=-1;
pDirent=readdir(pDir);
int count=0,count1=0,count2=0;
while(NULL!=pDirent)
{
printf("%s ",pDirent->d_name);
ret=stat(pDirent->d_name,&fileStat);
if(0==ret)
{
switch(fileStat.st_mode & S_IFMT)
{
case S_IFREG:count++;break;
case S_IFDIR:count1++;break;
default:count2++;break;
}
}
else if(-1==ret)
{
perror("stat");
break;
}
pDirent=readdir(pDir);
}
printf("\n");
printf("普通文件的個(gè)數(shù)為:%d\n",count);
printf("目錄文件的個(gè)數(shù)為:%d\n",count1);
printf("其他類型文件的個(gè)數(shù)為:%d\n",count2);
closedir(pDir);
}
//./a.out ../2
Paste_Image.png
進(jìn)程
- 如何創(chuàng)建進(jìn)程
- 如何使進(jìn)程之間通信
- 如何銷毀進(jìn)程
進(jìn)程與程序的區(qū)別
- 進(jìn)程是動(dòng)態(tài)的,程序是靜態(tài)的
- 一個(gè)程序可以運(yùn)行多個(gè)進(jìn)程,但是一個(gè)進(jìn)程只一個(gè)程序服務(wù)
進(jìn)程控制塊
如何查看一個(gè)正在運(yùn)行的進(jìn)程
- ps -A, kill -9 進(jìn)程號(hào)
如何查看進(jìn)程的運(yùn)行狀態(tài)
- top(表示CPU占了多少,占內(nèi)存多少)
如何創(chuàng)建進(jìn)程
- fork函數(shù)
- 子進(jìn)程會(huì)完全拷貝父進(jìn)程,包括代碼,包括資源
- 父進(jìn)程創(chuàng)建子進(jìn)程,然后返回,子進(jìn)程也返回,父進(jìn)程返回子進(jìn)程的pid,子進(jìn)程返回0
- 父進(jìn)程先返則先父進(jìn)程
#include <unistd.h> //fork()
#include <stdio.h>
#include <string.h>
int main(void)
{
pid_t pid = -1;
int iNum = 0;
char caData[32] = {'\0'};
//子進(jìn)程創(chuàng)建后,和父進(jìn)程屬于兩個(gè)相互獨(dú)立的進(jìn)程
//父進(jìn)程調(diào)用fork,這是一個(gè)系統(tǒng)調(diào)用,因此進(jìn)入內(nèi)核
//內(nèi)核根據(jù)父進(jìn)程復(fù)制出一個(gè)子進(jìn)程,父子進(jìn)程的PCB信息相同
//用戶態(tài)代碼和數(shù)據(jù)也完全相同。
//因此,子進(jìn)程現(xiàn)在的狀態(tài)看起來和父進(jìn)程一樣,做完了初始化
//剛調(diào)用了fork進(jìn)入內(nèi)核,還沒有從內(nèi)核返回。
//現(xiàn)在有兩個(gè)一模一樣的進(jìn)程看起來都調(diào)用了fork進(jìn)入內(nèi)核等待
//從內(nèi)核返回(實(shí)際上fork只調(diào)用了一次)。此外系統(tǒng)中還有其他
//進(jìn)程等待從內(nèi)核返回。是父進(jìn)程先返回還是子進(jìn)程先返回,還是
//父子進(jìn)程都等待,其他進(jìn)程先返回,這是不確定的。
//取決于內(nèi)核的調(diào)度算法
pid = fork();
//fork成功:將子進(jìn)程的id返回給父進(jìn)程的pid變量
// 將0返回給子進(jìn)程的pid變量
// 失敗:返回-1給父進(jìn)程的pid變量,子進(jìn)程不會(huì)被創(chuàng)建
// 并且錯(cuò)誤號(hào)會(huì)被設(shè)置
if (pid > 0) //父進(jìn)程
{
printf("this is parent process\n");
strcpy(caData, "this is parent process\n");
iNum = 3;
}
else if (0 == pid) //子進(jìn)程
{
printf("this is child process\n");
strcpy(caData, "this is child process\n");
iNum = 6;
}
else if (-1 == pid) //創(chuàng)建進(jìn)程失敗
{
perror("fork");
return -1;
}
int i = 0;
for (; i < iNum; i++)
{
printf("%s", caData);
sleep(1);
}
printf("Hello World\n");
return 0;
}
//父進(jìn)程先結(jié)束,則是由祖宗進(jìn)程對子進(jìn)程進(jìn)行善后
Paste_Image.png
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
pid_t pid=-1;
pid=fork();
if(pid>0)//父進(jìn)程
{
printf("this is parent progress\n");
}
else if(pid==0)//子進(jìn)程
{
printf("this is child progress\n");
}
else if(pid=-1)//創(chuàng)建進(jìn)程失敗
{
perror("fork");
return -1;
}
while(1)
{
}
printf("hello world\n");
return 0;
}
//后臺(tái)運(yùn)行:./a.out &
//同時(shí)創(chuàng)建兩個(gè)進(jìn)程:子進(jìn)程與父進(jìn)程
Paste_Image.png
Paste_Image.png
- 父進(jìn)程與子進(jìn)程之間相互獨(dú)立,父進(jìn)程創(chuàng)建子進(jìn)程,如果程序中不加while(1),則不能在后臺(tái)顯示,不加while(1)的結(jié)果如下:
Paste_Image.png
進(jìn)程如何殺死
- kill -9 +編號(hào)
僵尸進(jìn)程
- 子進(jìn)程結(jié)束后會(huì)釋放一些資源,但是有些資源需要父進(jìn)程進(jìn)行釋放,比如:進(jìn)程號(hào)
- 解決辦法:僵尸進(jìn)程,已死的進(jìn)程,但仍然在后臺(tái),kill不行,因?yàn)槭且阉赖倪M(jìn)程,只能殺死父進(jìn)程,最后由init祖宗進(jìn)程進(jìn)行
- 此為僵尸進(jìn)程只有殺死父進(jìn)程,則才能消滅子進(jìn)程,否則之間kill子進(jìn)程則仍然會(huì)在后臺(tái)顯示,雖然已經(jīng)殺死,但是父進(jìn)程沒有進(jìn)行清理,則仍然會(huì)存留(形成僵尸進(jìn)程實(shí)例)
#include <unistd.h>
#include <stdio.h>
#include <string.h>
//一個(gè)進(jìn)程結(jié)束時(shí)會(huì)關(guān)閉所有的文件描述符,
//釋放在用戶空間分配的內(nèi)存,
//但它的PCB還保留著,
//如果進(jìn)程異常終止則保留著導(dǎo)致該進(jìn)程終止的信號(hào)
//如果正常終止則保留退出狀態(tài):在終端可以用“$?”來查看
//父進(jìn)程可以調(diào)用wait或waitpid獲取這些信息,
//然后徹底清楚掉這個(gè)進(jìn)程
//如果一個(gè)進(jìn)程終止,但是其父進(jìn)程尚未調(diào)用wait或者waitpid
//對他進(jìn)行清理,這時(shí)的進(jìn)程狀態(tài)稱之為僵尸進(jìn)程。
//任何進(jìn)程在剛終止的時(shí)候都是僵尸進(jìn)程,
//正常情況下僵尸進(jìn)程會(huì)立刻被父進(jìn)程清理。
//僵尸進(jìn)程的危害:
// 系統(tǒng)允許存在的進(jìn)程數(shù)是有上限的。
// 若存在大量的僵尸進(jìn)程,則可能創(chuàng)建新的進(jìn)程由于沒有
// 進(jìn)程號(hào)分配而失敗
//形成僵尸進(jìn)程實(shí)例:
int main(void)
{
pid_t pid=-1;
pid=fork();
if(pid>0)//父進(jìn)程
{
printf("this is parent progress\n");
while(1)
{}
}
else if(pid==0)//子進(jìn)程
{
printf("this is child progress\n");
}
else if(pid=-1)//創(chuàng)建進(jìn)程失敗
{
perror("fork");
return -1;
}
while(1)
{}
}
Paste_Image.png
- 先刪除子進(jìn)程(結(jié)果如下,<defunct>,仍然存留在后臺(tái)中)
Paste_Image.png
- 刪除父進(jìn)程,結(jié)果如下:已清理好()
Paste_Image.png
- 此為另一種解決方案(出力僵尸進(jìn)程的方案)
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include<sys/wait.h>
#include<sys/types.h>
/*waitpid*/
//僵尸進(jìn)程的處理方式
//1.將子進(jìn)程的善后處理交給祖宗進(jìn)程(父進(jìn)程子在做自己的事,不方便對子進(jìn)程清理)
// A-->B-->C:將B進(jìn)程掛掉,那么C進(jìn)程的清理工作由祖宗進(jìn)程來清理
//2.父進(jìn)程自己調(diào)用相應(yīng)的函數(shù)來對子進(jìn)程做善后處理
int main(void)
{
pid_t pid=-1;
pid=fork();
if(pid>0)//父進(jìn)程
{
printf("this is parent progress\n");
//阻塞等待子進(jìn)程的結(jié)束
//獲得子進(jìn)程的退出狀態(tài),并對子進(jìn)程做清理工作
wait(NULL);
while(1)
{}
}
else if(pid==0)//子進(jìn)程
{
printf("this is first child progress\n");
pid_t pid2=fork();
if(pid2>0)
{
return 0;
}
else if(0==pid2)
{
int i=0;
for(;i<3;i++)
{
printf("this is second child process\n");
}
return 0;
}
}
else if(pid=-1)//創(chuàng)建進(jìn)程失敗
{
perror("fork");
return -1;
}
}
- 創(chuàng)建一個(gè)父進(jìn)程,寫數(shù)據(jù)到文件里,子進(jìn)程計(jì)算文件大小
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
/*open()*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
int fd=-1;
pid_t pid=1;
pid=fork();
if(pid>0)
{
fd=open(argv[1],O_RDWR | O_CREAT | O_APPEND,S_IRUSR | S_IWUSR | S_IRGRP);
if(-1==fd)
{
printf("open error:%s\n",strerror(errno));
return -1;
}
char *pData="hello world ";
int ret=-1;
while(1)
{
ret=write(fd,pData,strlen(pData));
if(-1==ret)
{
perror("write");
return -1;
}
sleep(1);
}
}
else if(0==pid)
{
fd=open(argv[1],O_RDWR | O_CREAT | O_APPEND,S_IRUSR | S_IWUSR | S_IRGRP);
off_t offset=-1;
while(1)
{
offset=lseek(fd,0,SEEK_END);
if(-1==offset)
{
perror("lseek");
return -1;
}
printf("file size:%ld\n",offset);
sleep(1);
}
}
else if(-1==pid)
{
perror("fork");
return -1;
}
return 0;
}
//運(yùn)行結(jié)果如下
Paste_Image.png