Linuxプロセスプログラミングの基礎

プロセスプログラミングの基礎

1. Fork()関数

この関数は、既存のプロセスから新しいプロセスを作成するために使用されます。新しいプロセスは子プロセスと呼ばれ、元のプロセスは親プロセスと呼ばれます。この関数を使用して取得される子プロセスは、親プロセスのコピーです。コンテキスト、コードセグメント、プロセススタック、メモリ情報、オープンファイル記述子、信号処理関数など、親プロセスからプロセス全体のアドレス空間を継承します。プロセスの優先順位、プロセスグループ番号、現在の作業ディレクトリ、ルートディレクトリ、リソース制限、制御端末など。子プロセスに固有の唯一のものは、そのプロセス番号、リソースの使用状況、およびタイマーです。
子プロセスは親プロセスのほぼ完全なコピーであるため、親プロセスと子プロセスは同じプログラムを実行します。したがって、ある方法でそれらを区別する必要があります。そうしないと、2つのプロセスは同じことしかできません。
親プロセスと子プロセスの最も重要な違いは、fork()の戻り値が異なることです。親プロセスの戻り値は子プロセスのプロセス番号であり、子プロセスの戻り値は0であるため、戻り値を使用して、プロセスが親プロセスであるか子プロセスであるかを判別できます。

函数原型:pid_t fork(void)
函数返回值:0 --- 子进程
		   大于0的正数(子进程PID) --- 父进程
		   -1 --- 出错

サンプルプログラム

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>

int main(int argc, const char *argv[])
{
    
    
	pid_t ret;
	ret = fork();		//调用fork()函数

	if(ret == -1){
    
    
		perror("fork error");
		return -1;
	}
	else if(ret == 0){
    
    		//返回值为0代表子进程
		printf("In child process!!ret is %d,My PID is %d\n",ret,getpid());
	}
	else{
    
    					//返回值大于0代表父进程
		printf("In parent process!!ret is %d,My PID is %d\n",ret,getpid());
	}

	return 0;
}

コンパイルして実行すると、結果は次のようになります。

linux@linux-virtual-machine:~/andy/proc$ gcc -o fork fork.c -Wall
linux@linux-virtual-machine:~/andy/proc$ ./fork 
In parent process!!ret is 2893,My PID is 2892
In child process!!ret is 0,My PID is 2893

2. exec関数ファミリー

exec関数ファミリーは、プロセス内で別のプログラムを実行する方法を提供します。指定されたファイル名またはディレクトリ名に従って実行可能ファイルを見つけ、それを使用して現在のプロセスのデータセグメント、コードセグメント、スタックセグメントを置き換えることができます。実行後、プロセス番号を除く現在のプロセスのすべての内容が置き換えられます。
Linuxでexec関数ファミリーを使用する主な状況は2つあります。

  • プロセスがシステムとユーザーに貢献できないと判断した場合、プロセスはexec関数ファミリの任意の関数を呼び出して、それ自体を再生成できます。
  • プロセスが別のプログラムを実行したい場合は、fork()関数を呼び出して新しいプロセスを作成し、アプリケーションを実行することによって新しいプロセスが生成されたように見える、exec関数ファミリーの関数のいずれかを呼び出すことができます。
函数原型:
int execl (const char *path,  const char *arg, ...)int execv (const char *path,  char *const argv[ ])int execle (const char *path,  const char *arg, ..., char *const envp[ ])int execve (const char *path,  char *const argv[ ], char *const envp[ ])int execlp (const char *file, const char *arg, ...)int execvp (const char *file,  char *const argv[ ])
函数返回值:-1 表示出错
exec関数名 対応する意味
トップ4 幹部として統合
5番 l:パラメータを渡すメソッドはリストメソッド(execl、execle、execlp)です。
v:パラメーターを渡すメソッドはvertorメソッド(execv、execve、execvp)です。
6番 e:新しいプロセス環境変数(execle、execve)を渡すことができます
p:実行ファイルの検索方法はファイル名(execlp、execvp)

サンプルプログラム

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>

int main (void)
{
    
    
	if(fork() == 0){
    
    
		/*注意命令参数列表以NULL结尾*/
		if((execlp("ps","ps","-ef",NULL)) < 0)  //逐个列举方式传递参数,文件名方式查找可执行文件
		//if((execl("/bin/ps","ps","-ef",NULL)) < 0)  //逐个列举方式传递参数,文件目录方式查找可执行文件
		//char *arg[] = {"env",NULL};	//命令参数列表,必须以NULL结尾
		//char *envp[] = {"PATH=/tmp","USER=harry",NULL};	//命令参数列表,必须以NULL结尾
		//if((execle("/usr/bin/env","env", NULL,envp)) < 0) 
		//if((execve("/usr/bin/env",arg, envp)) < 0)
			printf("execlp error\n");
	}	
}

上記のプログラムの実行結果は、シェルでコマンド「ps -ef」を直接入力した場合と同じです

3. Exit()および_exit()関数

exit()および_exit()関数は、プロセスを終了するために使用されます。この時点でプログラムが実行されると、プロセスは残りのすべての操作を無条件に停止し、すべてのデータ構造をクリアして、プロセスの操作を終了します。2つの違い:

  • _exit()関数はプロセスを直接停止し、プロセスが使用するメモリ空間とカーネル内のデータ構造をクリアします
  • exit()関数は、現在のプロセスを終了する前にプロセスが開いたファイルをチェックし、現在のプロセスを終了する前にファイルバッファーの内容をファイルに書き戻します。
函数原型:
void exit(int status)void _exit(int status)
函数传入值:
status是一个整型的参数,可以利用这个参数传递进程结束时的状态。一般,0表示正常结束;其他数值表示出现了错误,进程非正常结束

exit()サンプルプログラム

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    
    
	printf("Using exit...\n");
	printf("This is the content in buffer");
	exit(0);
}

コンパイルして実行すると、結果は次のようになります。

linux@linux-virtual-machine:~/andy/proc$ ./exit 
Using exit...
This is the content in buffer

_exit()サンプルプログラム

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    
    
	printf("Using exit...\n");
	printf("This is the content in buffer");
	_exit(0);
}

コンパイルして実行すると、結果は次のようになります。

linux@linux-virtual-machine:~/andy/proc$ ./exit 
Using exit...

4. wait()およびwaitpid()関数

wait()関数は、子プロセスが終了するか、プロセスが指定されたシグナルを受信するまで、親プロセス(つまり、wait関数を呼び出すプロセス)をブロックするために使用されます。親プロセスに子プロセスがないか、その子プロセスが終了した場合、すぐに-1が返されます
。waitpid()の機能はwait()と同じですが、必ずしも最初の子プロセスが終了するのを待つ必要はありません。いくつかのオプションがあり、wait()関数の非ブロッキングバージョンを提供できます。

/*******wait()函数*******/
函数原型:pid_t wait(int *status)
函数传入值:status 指向的整型对象用来保存子进程结束时的状态
函数返回值:成功---已回收的子进程的进程号;失败---返回-1

/******waitpid()函数*****/
函数原型:pid_t waitpid(pid_t pid, int *status, int options)
函数传入值:pid -->大于0,回收进程ID等于pid的子进程
			   -->等于-1,回收任一子进程,此时等同于wait()
			   -->等于0,回收其组ID等于调用进程的组ID的任一子进程
			   -->小于-1,回收其组ID等于pid的绝对值的任一子进程
		   status 指向的整型对象用来保存子进程结束时的状态
		   options -->WNOHANG,若指定的子进程没有结束,则waitpid()不阻塞而立即返回0
		   		   -->WUNTRACED,为了实现某种操作,有pid指定的任一子进程已被暂停,
		   		      且其状态还未报告过,则返回其状态
		   		   -->0,同wait(),阻塞父进程,直到指定的子进程退出	   
函数返回值:大于0, 已经结束运行的子进程的进程号
		   等于0,使用WNOHANG且没有子进程退出
		   等于-1,出错

サンプルプログラム

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    
    
	pid_t pid,ret;

	if((pid = fork()) < 0){
    
    
		printf("Error fork\n");
	}
	else if(pid == 0){
    
    
		sleep(5);
		exit(0);	//子进程正常退出
	}
	else{
    
    
		
		do{
    
    			//循环测试子进程是否退出
			ret = waitpid(pid,NULL,WNOHANG);	//调用waitpid,且父进程不阻塞
			if(ret == 0){
    
    		//若子进程还未退出,则父进程暂停1s
				printf("The child process has not exited\n");
				sleep(1);
			}
		}while( ret == 0);
	
		if( pid == ret)		//若发现子进程退出,打印出相应情况
			printf("child process exited\n");
		else
			printf("some error occured\n");
	}
}

コンパイルして実行すると、結果は次のようになります。

linux@linux-virtual-machine:~/andy/proc$ ./waitpid 
The child process has not exited
The child process has not exited
The child process has not exited
The child process has not exited
The child process has not exited
child process exited

5.プロセス関連のコマンド

  • psは現在アクティブなプロセスを示します
  • 上部には実行中のすべてのプロセスが表示されます
  • / procこのディレクトリには、システムで現在実行されている各プロセスの情報が格納されます
  • niceはプロセスの優先順位を変更します
  • reniceの使用法はniceコマンドと同じですが、違いは、実行中のコマンドのスケジューリング優先度を更新できることです。
  • マウントされたプロセスを表示する
  • bgは停止またはバックグラウンドプロセスをリストします
  • fgは最新のプロセスを前面に表示します
  • プロセスを閉じるためにkill

おすすめ

転載: blog.csdn.net/Chuangke_Andy/article/details/108278004