1. 程式人生 > >linux下多程序的檔案拷貝與程序相關的一些基礎知識

linux下多程序的檔案拷貝與程序相關的一些基礎知識

之前實現了用檔案IO的方式可以實現檔案的拷貝,那麼對於程序而言,我們是否也可以實現呢?

答案是肯定的。

程序資源:

首先我們先回顧一下,程序的執行需要哪些資源呢?其資源包括CPU資源,記憶體資源,當然還有時間片資源,我們都知道程序是有 棧, 堆,  只讀資料段,  資料段(已初始化的全域性變數靜態變數),bss段(未初始化的),   程式碼段還有一組暫存器值。

程序命令:

另外我們也可以通過 ps  -ef |grep 程序名命令來檢視程序號(PID)和父程序號(PPID),之後還可以通過  

ps aux |grep 程序名或程序號來檢視程序的狀態(R,T,S,Z,(+)...).通過 kill -訊號的序號或巨集  PID

來對訊號發各種訊號,注意這裡面的kill可不是殺死程序的意思,我們可以通過給程序發訊號來殺死程序kill -SIGKILL PID  ,當然我們可以通過 kill -l 來獲取巨集名,其次我們通過nice 或renice來給我們的程序設定不同的優先順序,等等等等。

程序建立:

我們會用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中。如果有哪裡需要改進希望留言給我哈