【Linuxプログラミング】プロセス制御&デーモンプロセス

13508 ワード

このシリーズのブログは私が2年生の时にLinuxシステムの高度なプログラミングを学んだ时のいくつかの実験プログラムで、すべてとても简単です.
実験テーマ:Linux環境下でのプロセス制御
実験目的:Linux環境下のプロセスに関する関数の応用を熟知し、把握する.プロセスの概念、起動、操作を守ります.プロセスオペレータの作成.
一、Linuxプロセス制御
以下の要件を満たすようにプログラムを設計します.
1、Linuxシステムがこのプログラムに割り当てたプロセス番号(PID)とその親プロセス番号(PPID)を表示するプログラムを設計する.
Linux環境でプロセスが作成されると、各プロセスに一意の数値が割り当てられます.この数値をプロセス識別子(pid)と呼び、親プロセス番号をppidで表します.
Linuxで現在のプロセスのpid、ppidを取得すると、getpid()およびgetppid()関数を呼び出すことができます.
getpid関数の説明は次のとおりです.
必要なヘッダファイル
#include
関数の機能
現在のプロセスのプロセス番号を取得
関数プロトタイプ
pid_t getpid(void)
関数の入力値
なし
戻り値
現在のプロセスの識別子が正常に返されました
 
必要なヘッダファイル
#include
関数の機能
現在のプロセスの親プロセス番号を取得
関数プロトタイプ
pid_t getppid(void)
関数の入力値
なし
戻り値
現在のプロセスの親プロセス識別子が正常に返されました
 
1 #include<stdio.h>
2 #include<unistd.h>
3 int main()
4 {
5     printf(" (PID) :%d
",getpid()); 6 printf(" (PPID) :%d
",getppid()); 7 return 0; 8 }

 
2、fork関数でサブプロセスを作成するプログラムを設計し、サブプロセスで変数nに3を割り当て、親プロセスで変数nに6を割り当て、fork呼び出し後、親プロセスとサブプロセスの変数messageとnに異なる値を与え、互いに影響しない.
Linuxでfork()関数を呼び出すと、forkによって作成された新しいプロセスをサブプロセスと呼ぶ新しいプロセスを作成できます.fork()関数は、サブプロセスの戻り値が0であり、親プロセスの戻り値がサブプロセスのpidであることを区別して、1回に2回戻ります.サブプロセスは、親プロセスのレプリカ、親プロセスのデータ空間、スタックなどをコピーします.
必要なヘッダファイル
#include
機能
新しいプロセスを確立する
 
 
関数プロトタイプ
pid_t fork(void)
入力値
なし
戻り値
実行成功サブプロセスで0を返し、親プロセスでサブプロセスのpidを返し、失敗して-1を返します.
 
 
 1 #include<stdio.h>
 2 #include<sys/types.h>
 3 #include<stdlib.h>
 4 #include<unistd.h>
 5 int main()
 6 {
 7     pid_t pid;
 8     char *message;
 9     int n;
10     pid = fork();
11     if(pid < 0)
12     {
13         perror("fork failed!
"); 14 exit(1); 15 } 16 if(pid == 0) 17 { 18 message="This is the child!
"; 19 n=3; 20 } 21 else 22 { 23 message="This is the parent!
"; 24 n=6; 25 } 26 for(;n>0;n--) 27 { 28 printf(message); 29 sleep(1); 30 } 31 32 return 0; 33 }

 
3、それぞれexec関数ファミリーの6つの関数を使用してコマンド「ifconfig eth 0 192.168.110.140」を実行します.
#include<stdio.h>
#include<stdlib.h>
// exec , 。
#include<unistd.h>
#include<sys/types.h>

int main()
{
    char *const argv[]={"ifconfig","eth0","192.168.110.140",NULL};
    char *env[]={"PATH=bin:usr/sbin",NULL};
//    execl("/sbin/ifconfig","ifconfig","eth0","192.168.110.140",NULL);
//    execv("/sbin/ifconfig",argv);
//    execle("/sbin/ifconfig","ifconfig","eth0","192.168.110.140",NULL,env);
//    execve("/sbin/ifconfig",argv,env);
//    execlp("ifconfig","ifconfig","eth0","192.168.110.140",NULL);
    execvp("ifconfig",argv);
    return 0;
}

 
システムでプロセスを作成する目的は、プロセスが一定のタスクを完了する必要があり、そのプロセスが彼のプログラムコードを実行する必要があり、Linuxシステムでexec関数を呼び出すことができるのはプログラム実行です.
システム呼び出しexecには、execファミリーと呼ばれる多くの使用形態があります.パラメータが異なるだけで、機能は同じです.
exec族の中で6つの関数はサブプロセスを創立することができて、それぞれexecl、execcv、execle、execve、execlp、execvp、関数の中で5、6番目の文字l、v、e、pは関数の中国のパラメータを表してそれぞれリストで方式を伝達して、文字の伝達方式、環境変数と経路の自動検索機能を制定することができます.
必要なヘッダファイル
#include
関数プロトタイプ
int execl(const char *path,const char *arg, ...) int execv(consr char *path,char const *argv[]) int execle(consr char *path, const char *arg, ... ,char const * envp[]) int execve(consr 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エラー
実際、この6つの関数の中で本当のシステム呼び出し関数はexecve()だけで、他の5つはライブラリ関数で、彼らが最終的に呼び出したのはexecveというシステム関数です.
exec呼び出しの例は次のとおりです.
1 char *const ps_argv[] = {"ps","-o", "pid,ppid",NULL};
2 char *const ps_envp[] = {"PATH = bin:/usr/bin","TERM = console",NULL};
3 
4 execl("bin/ps","ps","-o","pid,ppid",NULL);
5 execv("bin/ps",ps_argv);
6 execle("bin/ps","ps","-o","pid,ppid",NULL,ps_envp);
7 execve("bin/ps",ps_argv,ps_envp);
8 execlp("ps","ps","-o","pid,ppid",NULL);
9 execvp("ps",ps_argv);

 
二、ゾンビプロセス
1.サブプロセスの作成を要求するプログラムを設計し、サブプロセスが自分のプロセス番号(PID)を表示した後、しばらく一時停止し、親プロセスはサブプロセスが正常に終了するのを待って、待機しているプロセス番号(PID)と待機しているプロセスの終了状態を印刷表示する.
 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<unistd.h>
 4 #include<sys/types.h>
 5 #include<sys/wait.h>
 6 int main()
 7 {
 8     pid_t pid,wpid;
 9     int status,i;
10     pid =fork();
11     if(pid ==0)
12     {
13         printf("This is the child, (PID) :%d
",getpid()); 14 sleep(5); 15 exit(6); 16 } 17 else 18 { 19 printf("This is the parent, .....
"); 20 wpid=wait(&status); 21 i=WEXITSTATUS(status); 22 printf(" (PID) :%d, :%d
",wpid,i); 23 } 24 return 0; 25 }

 
2、サブプロセスはsleepで10秒待ち、親プロセスはwaitpid関数でサブプロセスが正常に終了するのを待ち、親プロセスは待機中にブロックされず、1秒ごとに画面に1行の文字を出力し、サブプロセスが終了したことを発見したら、待機プロセスのプロセス番号(PID)と終了状態を印刷する.デバッグのためのプログラムを作成してください.
#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
    pid_t pid,wpid;
    int status;
    pid=fork();
    if(pid==0)
    {
        printf("This is the child, (PID) :%d
",getpid()); printf("This is the child,Then slepp now!
"); sleep(10); exit(6); } else { printf("This is the parent!
"); while(1){ waitpid(pid, &status, WNOHANG); printf("Wait for child.........
"); if(0 == WIFEXITED(status)) sleep(1); else{ printf("Child is end now!
"); printf(" (PID) :%d, :%d
",pid,WEXITSTATUS(status)); break; } } } }

 
三、プロセスを守る
1、
プログラムを作成し、実行後にデーモンプロセスとなり、3秒おきに自機のIPアドレスを変更し、画面にIPアドレス情報を表示する.
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<unistd.h>
#include<sys/param.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<signal.h>
void init_daemon(void)
{
    pid_t child1,child2;
    int i;
    child1=fork();
    if(child1 >0)
        exit(0);
    else if(child1 < 0) 
    {
        perror("
"); exit(1); } setsid(); chdir("/mnt/hgfs/zhaoshun"); umask(0); for(i=0;i<NOFILE;++i) close(i); return; } int main() { FILE * fp; char buf1[100],buf2[100]; init_daemon(); if((fp=fopen("ipadd","r"))=NULL) { printf("
"); } while(1) { ifconfig(); system("ifconfig"); sleep(3); } return 0; }