【Linux程序設計】之進程控制&守護進程


這個系列的博客貼的都是我大二的時候學習Linux系統高級編程時的一些實驗程序,都挺簡單的。

實驗題目:Linux環境下的進程控制

實驗目的:熟悉並掌握Linux環境下進程的相關函數的應用;守護進程的概念、啟動和操作;進程操作程序的編寫。

一、Linux進程控制

設計程序,滿足如下要求:

1、設計一個程序,要求顯示Linux系統分配給此程序的進程號(PID)和它的父進程號(PPID)。

在Linux環境下進程創建時,系統會分配一個唯一的數值給每個進程,這個數值就稱為進程標示符(pid),他的父進程號用ppid表示。

在Linux中獲取當前進程的pid、ppid可以調用getpid()和getppid()函數。

getpid函數說明如下:

所需頭文件 #include<unsitd.h>
函數功能 取得當前進程的進程號
函數原型 pid_t getpid(void)
函數傳入值
返回值 成功返回當前進程的標識符

 

所需頭文件
#include<unistd.h>
函數功能 取得當前進程的父進程號
函數原型 pid_t getppid(void)
函數傳入值
返回值 成功返回當前進程的父進程標識符

 

1 #include<stdio.h>
2 #include<unistd.h>
3 int main()
4 {
5     printf("系統分配的進程號(PID)是:%d\n",getpid());
6     printf("系統分配的父進程號(PPID)是:%d\n",getppid());
7     return 0;
8 }

 

2、設計一個程序,用fork函數創建一個子進程,在子進程中給變量n賦值3,在父進程中給變量n賦值6,fork調用之后父進程和子進程的變量message和n被賦予不同的值,互不影響。

Linux下調用fork()函數可以創建一個新進程,由fork創建的新的進程被稱為子進程。fork()函數調用一次返回兩次,區別是子進程的返回值是0,父進程的返回值是子進程的pid。子進程是父進程的復制品,復制父進程的數據空間,堆棧等。

所需頭文件 #include <unistd.h>
功能 建立一個新的進程
   
函數原型 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!\n");
14         exit(1);
15     }
16     if(pid == 0)
17     {
18         message="This is the child!\n";
19         n=3;
20     }
21     else
22     {
23         message="This is the parent!\n";
24             n=6;
25     }
26     for(;n>0;n--)
27     {
28         printf(message);
29         sleep(1);
30     }
31 
32     return 0;
33 }

 

3、分別使用exec函數族中的六個函數執行命令“ifconfig eth0 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 <unistd.h>
函數原型

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出錯

而事實上,這六個函數中真正的系統調用函數只有execve(),其他的五個都是庫函數,他們最終調用的都是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\n",getpid());
14         sleep(5);
15         exit(6);
16     }
17     else
18     {
19         printf("This is the parent,正在等待子進程.....\n");
20         wpid=wait(&status);
21         i=WEXITSTATUS(status);
22         printf("等待進程的進程號(PID)是:%d,結束狀態:%d\n",wpid,i);
23     }
24     return 0;
25 }

 

2、要求子進程用sleep等待10秒,父進程用waitpid函數等待子進程正常結束,父進程在等待的時候不阻塞,每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\n",getpid());
        printf("This is the child,Then slepp now!\n");
        sleep(10);
        exit(6);

    }
    else
    {
        printf("This is the parent!\n");
        while(1){
        waitpid(pid, &status, WNOHANG);
        printf("Wait for child.........\n");
        if(0 == WIFEXITED(status))
        sleep(1);
        else{
        printf("Child is end now!\n");
        printf("等待的進程的進程號(PID)是:%d,結束狀態:%d\n",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("創建子進程失敗!\n");
        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("打開文件出錯!\n");
    }

    while(1)

    {
        ifconfig();

        system("ifconfig");
        sleep(3);

    }

    return 0;


}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM