linux下多程序的檔案拷貝與程序相關的一些基礎知識
之前實現了用檔案IO的方式可以實現檔案的拷貝,那麼對於程序而言,我們是否也可以實現呢?
答案是肯定的。
程序資源:
首先我們先回顧一下,程序的執行需要哪些資源呢?其資源包括CPU資源,記憶體資源,當然還有時間片資源,我們都知道程序是有 棧, 堆, 只讀資料段, 資料段(已初始化的全域性變數靜態變數),bss段(未初始化的), 程式碼段還有一組暫存器值。
程序命令:
另外我們也可以通過 ps -ef |grep 程序名命令來檢視程序號(PID)和父程序號(PPID),之後還可以通過
ps aux |grep 程序名或程序號來檢視程序的狀態(R,T,S,Z,(+)...).通過 kill -訊號的序號或巨集 PID
程序建立:
我們會用fork函式來建立程序,以前我們都很清除的知道,一個函式只可以返回一個返回值,那麼程序建立的函式也只返回一個麼?答案是不對的,因為通過fork函式建立的程序,如果成功的話我們向父程序返回子程序的PID號,向子程序返回0,如果建立失敗,則向父程序返回-1。建立完子程序後,父程序從fork()的下一條語句開始執行,子程序也是從下一條語句執行麼?
是的,因為建立子程序的時候拷貝父程序的pc暫存器值,而pc暫存器的值決定了你的程序是從什麼地方開始的,所以當建立完子程序後,我們的子程序的執行與父程序的執行系一樣的方式,但是注意他們兩個不是一塊進行的,也有先後關係,只是先後關係不確定,如果用vfork函式建立程序的話,那麼我們的子程序是先進行的。
那麼上面說了fork()函式與vfork()函式都可以建立程序,有什麼區別呢?
<1>fork建立子程序後,父子程序執行的順序是不確定的,父子程序的地址空間是獨立的。
<2>vfork建立完子程序後,保證子進先執行,父程序在子程序結束,或呼叫exec函式族後才開始執行,
並且父子程序共享同一地址空間【如果子程序呼叫了exec函式則子程序會獨立出來】。
那麼怎樣利用程序來進行檔案的拷貝呢?以及怎樣拷貝呢?具體實現的要求如下,父程序拷貝檔案的前一半子程序拷貝檔案的後一半,那麼效率上面我們肯定比一個程序高得多了,以上就是對程序知識的相關回顧,知識點有了,思路有了,那麼剩下的就只是程式碼實現的問題了,也就是體力勞動了:
請看下面程式碼的實現:
#include <head.h>
int child_copy(int fd_src,int fd_dest,int file_size)
{
int ret;
int n;
char buf[1024];
ret = lseek(fd_src,file_size/2,SEEK_SET);
if(ret < 0)
{
perror("Fail to src_file lseek");
exit(EXIT_FAILURE);
}
ret = lseek(fd_dest,file_size/2,SEEK_SET);
if(ret < 0)
{
perror("Fail to dest_file lseek");
exit(EXIT_FAILURE);
}
while(1)
{
n = read(fd_src,buf,sizeof(buf));
if(n == 0)
break;
write(fd_dest,buf,n);
}
return 0;
}
int parent_copy(int fd_src,int fd_dest,int size)
{
int n;
int count = 0;
char buf[1024];
while(1)
{
// lseek(fd_src,0,SEEK_SET);
// lseek(fd_dest,0,SEEK_SET);
n = read(fd_src,buf,sizeof(buf));
write(fd_dest,buf,n);
count += n;
if(count >= size/2)
break;
}
return 0;
}
// ./a.out src_file dest_file
int main(int argc, const char *argv[])
{
pid_t pid;
int file_size; //the size of file
int fd_src,fd_dest;
struct stat f_info;
if(argc < 3)
{
fprintf(stderr,"Usage :%s argv[1] argv[2]\n",argv[0]);
exit(EXIT_FAILURE);
}
if(stat(argv[1],&f_info) < 0)
{
fprintf(stderr,"Fail to stat %s: %s",argv[1],strerror(errno));
exit(EXIT_FAILURE);
}
file_size = f_info.st_size; //get the size of file
fd_src = open(argv[1],O_RDONLY);//open the file
if(fd_src < 0)
{
fprintf(stderr,"Fail to open %s : %s\n",argv[1],strerror(errno));
exit(EXIT_FAILURE);
}
fd_dest = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666);
if(fd_src < 0)
{
fprintf(stderr,"Fail to open %s : %s\n",argv[2],strerror(errno));
exit(EXIT_FAILURE);
}
if(ftruncate(fd_dest,file_size) < 0) //create a empty file
{
perror("fail to ftruncate");
exit(EXIT_FAILURE);
}
pid = fork();
if(pid < 0)
{
fprintf(stderr,"Fail to fork\n",strerror(errno));
exit(EXIT_FAILURE);
}
if(pid == 0)
{
close(fd_src);
close(fd_dest);
fd_src = open(argv[1],O_RDONLY);//open the file again
if(fd_src < 0)
{
fprintf(stderr,"Fail to open %s : %s\n",argv[1],strerror(errno));
exit(EXIT_FAILURE);
}
fd_dest = open(argv[2],O_WRONLY);
if(fd_src < 0)
{
fprintf(stderr,"Fail to open %s : %s\n",argv[2],strerror(errno));
exit(EXIT_FAILURE);
}
child_copy(fd_src,fd_dest,file_size);
}
if(pid > 0)
{
// getchar();
parent_copy(fd_src,fd_dest,file_size);
}
return 0;
}
注:
本程式用到的標頭檔案本人直接封裝在了head.h中。如果有哪裡需要改進希望留言給我哈