zoukankan      html  css  js  c++  java
  • 【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
    ",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。子进程是父进程的复制品,复制父进程的数据空间,堆栈等。

    所需头文件 #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!
    ");
    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函数族中的六个函数执行命令“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
    ",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秒在屏幕上输出一行文字,若发现子进程退出,打印等待进程的进程号(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;
    
    
    }
  • 相关阅读:
    NeHe OpenGL教程 第三十四课:地形
    NeHe OpenGL教程 第三十三课:TGA文件
    NeHe OpenGL教程 第三十二课:拾取游戏
    NeHe OpenGL教程 第三十一课:加载模型
    NeHe OpenGL教程 第三十课:碰撞检测
    58. Extjs grid CheckboxSelectionModel 单选
    57.部门职位管理 ExtJs 展示
    56. EditorGridPanel和渲染器renderer的使用
    55. GridPanel中getSelectionModel详解
    54. Extjs组件render说明
  • 原文地址:https://www.cnblogs.com/msxh/p/4947909.html
Copyright © 2011-2022 走看看