第二の実験オペレーティングシステム:プロセス制御
16281035
私のgithubのウェブサイト、どのアクティブなファイルには、以下を参照してください
実験の目的
- 、プロセスと手順を明確に区別し、プロセスの概念の理解を深め。
- 創造のプロセスを習得し、他の管理と運用を削除するには、Linuxシステム。
- ようにと|な男、見つける、grepを、whereisは、PS、のpgrep、殺す、ptreeで、トップ、vimの、GCC、GDB、パイプラインなどのLinuxでのコマンドやツールに精通。
基本
- 作成プロセス
Linuxは、メモリにロードされ、操作を実行し、操作が分割され、新たなプログラムの画像処理を作成します。プログラムイメージがメモリにロードされ、それを実行を開始、対応するシステムとして知られている新しいプログラムを実行することが知られているプロセスは、execシステムコールを呼び出します。また、新しいプロセスを作成することはフォークシステムコールのシステムコールです。
- execシステムコール
書式#include <unistd.h>
int型のEXECL(定数のchar *のパス、CONSTのchar *引数、...);
メモリ経路に画像パスの意味の範囲内EXECL()は、その最初のパラメータをargを。可変長パラメータ。引数リストは、NULLで終了する必要があります。
通常EXECL()は戻りません。呼び出しが成功すると、エンドとして新しいエントリポイントにジャンプします。エラーが発生した場合、EXECL()は-1を返し、errno値。
例編集/home/kidd/hooks.txt:
int型のRET;
RET = EXECL( "/ binに/私たち"、 "私たち"、 "/ホーム/キッド/ hooks.txt"、NULL);
(RET == -1)の場合
perrorは(」EXECL」);
- システムコールフォーク****
書式#include <SYS / types.h>に
書式#include <unistd.h>
pid_tフォーク(ボイド)。
フォークへの呼び出しが成功()は、フォーク()処理を呼び出すとほぼ同じ、新しいプロセスを作成します。エラーが発生したときに、フォーク()は-1を返し、errno値。
例:
pid_t pidを。
PID =フォーク()。
(PID> 0)であれば
printf(」私は、PID =%dは親だ\ nは!」、PID);
それ以外の場合(!のPID)
printf(」私は赤ちゃんだ\ nは!」);
他の(PID == -1)の場合
perrorは(」フォーク」)。
- プロセスを終了
終了()システムコール:
書式#include <stdlib.h>に含ま
空の出口(int型の状態)。
- プロセスがハング
()システムコールを一時停止します:
int型の一時停止(無効)。
信号が受信されるまで一時停止機能は、プロセスを停止します。信号を受信した後、プロセスは、一時停止機能を終了動作し続けます。
- 待って(子供が中断または終了を待ちます)
書式#include <SYS / types.h>に
書式#include <sysの/ wait.h>
pid_t待機(int型*ステータス)。
一時的に現在のプロセスの実行を停止します)(待つ、または存在するまで子プロセスへの信号が終了します。
子プロセスが終了した場合は()待機を呼び出すときに、待ち()直後に子プロセスの終了ステータス値を返します。
子プロセスが識別コードと共に返されるつつ、終了状態値は、子プロセスパラメータの状態によって返されます。
終了状態が値を気にしない場合は、ステータスパラメータがNULLに設定することができます。
VIMクイックは、通常のコマンドを使用しました
実験対象
1. viのプロセスを開きます。psコマンドによって、および適切なパラメータ、VIのプロセスのための唯一の名前を選択します。これまでのinitプロセスまで、viの親プロセスを探しています。プロセスIDとすべてのプロセスの親プロセスIDを記録します。その結果、プロセスツリーとpstreeはコマンドでプロセスツリーを取得して比較しました。
-
まず、私はvimので開かれ、その後、vimのVIと呼ばれるファイル自身を作成します
-
オープンインタフェースは、次のとおりです。
私は次のように編集する編集コマンドを有効にします:
-
保存
-
ビューVimのプロセスID、5065
![1552705140843](https://img-blog.csdnimg.cn/20190316114007384.png
-
寻找vim进程的父进程,直到init进程为止。记录过程中所有进程的ID和父进程ID
init进程的pid是1.init进程是其他所有进程的父进程.
列出父进程号是1的进程,就是列出除了init外的所有进程.
所以寻找vim的父进程如下:
5065 -> 4626 -> 4619 -> 908 -> 1
-
将得到的进程树和由pstree命令的得到的进程树进行比较。
两个相比较,是一样的结果: 5065 -> 4626 -> 4619 -> 908 -> 1
2、编写程序,首先使用fork系统调用,创建子进程。在父进程中继续执行空循环操作;在子进程中调用exec打开vi编辑器。然后在另外一个终端中,通过ps –Al命令、ps aux或者top等命令,查看vi进程及其父进程的运行状态,理解每个参数所表达的意义。选择合适的命令参数,对所有进程按照CPU占用率排序。
-
程序代码 fork.c
#include <unistd.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]){ pid_t pid = fork(); //在子进程 if(pid == 0) { int num = execl("/usr/bin/vim","vim","NULL"); if(num == -1) perror("execl"); } else if(pid>0) { //在父进程 while(1){} } else { printf("fork调用失败"); } return (0); }
-
运行结果:打开了vim
-
查看vi进程及父进程的运行状态以及各个参数的意思:
-
选择合适的命令参数,对所有进程按照CPU占用率排序
3、使用fork系统调用,创建如下进程树,并使每个进程输出自己的ID和父进程的ID。观察进程的执行顺序和运行状态的变化。
- 首先对fork()函数调用进行简单的测试
运行结果
输出两个hello
だから、:元のプロセスとほぼ同じプロセスを作成するためのシステムを介し関数呼び出し、新しく作成されたプロセスは子プロセスと呼ばれています。プロセスは、システムは、データ及びコードを格納するためのスペースとして、新しいプロセスを与えるためにリソースを割り当て、関数の後フォーク()を呼び出します。その後、元のすべての値は、新しいプロセスの新しいプロセスにコピーされ、元のプロセスと異なる値だけでいくつかの値。自分自身のクローンの同等。もう一つ注意すべき:fork関数を呼び出した後、それがコードの同じスニペットに2つのプロセスでなければならないことは、前のコードのに対し、fork関数の後に実行され、親プロセスが完了することによって行われます。
次のようにフォーク()戻り値の意味は以下の通りであります:
= 0:子で
0:親プロセスで
<0:作成に失敗しました
-
ソースfork3.c
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> #include <time.h> #include <stdarg.h> #include<sys/types.h> //这个头文件不能少,否则pid_t没有定义 int main(int argc, char *argv[]) { pid_t pidA,pidB,pidC,pidD; printf("这是父进程,P1,PID是%d\n",getpid()); pidA = fork(); //创建新进程 if(pidA<0) { printf("新进程创建失败\n"); return 0; } else if(pidA == 0) { printf("这是子进程,P3,PID是%d\n",getpid()); return 0; } else { pidB = fork(); if(pidB<0) { printf("新进程创建失败\n"); return 0; } else if(pidB == 0) { printf("我是子进程,P2,PID是%d\n",getpid()); pidC = fork(); if(pidC == 0) { printf("这是子进程,P4,PID是%d\n",getpid()); return 0;//防止产生孙进程 } pidD = fork(); if(pidD == 0) { printf("这是子进程,P5,PID是%d\n",getpid()); return 0;//防止产生孙进程 } } } return 0; }
-
業績
-
コードの改良:私は、上記のようなコードを発見した親または子プロセスが実行中に残っているかどうか、停止しません。
だから私は、元の基礎に次のコードを追加しました:
int *status; waitpid(pidC,status, 0); waitpid(pidD,status, 0); return 0; } } int *status; waitpid(pidB,status, 0); waitpid(pidA,status, 0); return 0;
自動的に得られた結果は、実行を停止します
図4は、上述したプロセスは、すべてのプロセスが環状自身のIDであるように、プロセスツリーを変更し、親プロセスのIDを出力します。その後、変更された(それぞれ、自身の通常の出口出口を(-9を殺す)、セグメンテーション違反出口)プロセスP2を終了P1、P3、P4、P5の稼働状況プロセスおよびその他の関連パラメータを観察します。
-
殺す-9
5228の後、プロセスP2、プロセス番号を殺すには、PPIDのP4とP5は、もはや5228ではありません、と895になりました。
私はルートプロセスの最も原始的に同等であるプロセスツリー、見つかっにsystemd(895)、照会します。だから私は多くの質問があります。
(1)親のなぜこれらの「孤児」子プロセスPPIDの損失がsystemdにされていない(1)?
(2)にsystemd(1)とにsystemd(895)それとの間の関連は何ですか?
-
自身の正常な終了
ソース
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> #include <time.h> #include <stdarg.h> #include<sys/types.h> //这个头文件不能少,否则pid_t没有定义 int main(int argc, char *argv[]) { pid_t pidA,pidB,pidC,pidD; int i; printf("这是父进程,P1,PID是%d\n",getpid()); pidA = fork(); //创建新进程 if(pidA<0) { printf("新进程创建失败\n"); exit(0); } else if(pidA == 0) { i=100; while(i-->0) { printf("这是子进程,P3,PID是%d 它的父进程,P1,PID是%d\n",getpid(),getppid()); } return 0; } else { pidB = fork(); if(pidB<0) { printf("新进程创建失败\n"); return 0; } else if(pidB == 0) { i=100; pidC = fork(); if(pidC == 0) { i=100; while(i-->0){ printf("这是子进程,P4,PID是%d 它的父进程,P2,PID是%d\n",getpid(),getppid());} return 0;//防止产生孙进程 } pidD = fork(); if(pidD == 0) { i=100; while(i-->0){ printf("这是子进程,P5,PID是%d 它的父进程,P2,PID是%d\n",getpid(),getppid()); } return 0;//防止产生孙进程 } i=100; while(i-->0) { printf("这是子进程,P2,PID是%d 它的父进程,P1,PID是%d\n",getpid(),getppid()); if(i==50) { exit(0); } } int *status; waitpid(pidC,status, 0); waitpid(pidD,status, 0); return 0; } } int *status; waitpid(pidB,status, 0); waitpid(pidA,status, 0); return 0; }
結果:
そして、同じ結果を求めて最初の、それはあまりにも速く走る、フロントエンドの一部をキャプチャするのに十分な時間ではありません自動的にではありません。
3.終了ミス
ソース
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <time.h>
#include <stdarg.h>
#include<sys/types.h> //这个头文件不能少,否则pid_t没有定义
int main(int argc, char *argv[])
{
pid_t pidA,pidB,pidC,pidD;
int i;
printf("这是父进程,P1,PID是%d\n",getpid());
pidA = fork(); //创建新进程
if(pidA<0)
{
printf("新进程创建失败\n");
exit(0);
}
else if(pidA == 0)
{
i=100;
while(i-->0)
{
printf("这是子进程,P3,PID是%d 它的父进程,P1,PID是%d\n",getpid(),getppid());
}
return 0;
}
else
{
pidB = fork();
if(pidB<0)
{
printf("新进程创建失败\n");
return 0;
}
else if(pidB == 0)
{
i=100;
pidC = fork();
if(pidC == 0)
{
i=100;
while(i-->0){
printf("这是子进程,P4,PID是%d 它的父进程,P2,PID是%d\n",getpid(),getppid());}
return 0;//防止产生孙进程
}
pidD = fork();
if(pidD == 0)
{
i=100;
while(i-->0){
printf("这是子进程,P5,PID是%d 它的父进程,P2,PID是%d\n",getpid(),getppid());
}
return 0;//防止产生孙进程
}
i=100;
while(i-->0)
{
printf("这是子进程,P2,PID是%d 它的父进程,P1,PID是%d\n",getpid(),getppid());
if(i==50) {
int *ptr = NULL;
*ptr = 0;
}
}
int *status;
waitpid(pidC,status, 0);
waitpid(pidD,status, 0);
return 0;
}
}
int *status;
waitpid(pidB,status, 0);
waitpid(pidA,status, 0);
return 0;
}
結果:
ミスが上記の結果、P2からの出口には影響しないのだろうか?それはまだ親プロセスP4とP5です。