linux and Windows Process Control

Process management control

Implemented here is a custom timer for time statistics sub-processes running. Use mainly

timer [-t seconds] command arguments

For example, to count lsthe running time can be entered directly timer ls, followed by argumentsmeans of the parameters of the program to run. Such timer ls -alas: . If you want to specify how much time to run the program, such as five seconds, you can enter timer -t 5 ls -al. It should be noted that the program did not do the input anomaly detection, so be sure to enter the correct procedures.

Linux

Ideas program

  1. Get Time

    Time acquisition function is used gettimeofday, the microsecond accuracy

    struct timeval{
         long tv_sec;*//秒*
         long tv_usec;*//微秒*
    }
  2. Create a child process

    1. fork()function

      #include <sys/types.h>
      #include <unistd.h>
      pid_t fork(void);

      forkCall fails -1 is returned, the call was successful:

      fork function return value will be two, one is zero, one is a positive integer. If 0, then the current process as the child process; if it is a positive integer, then the process is the parent process and a child process pid. For details on the process control, refer to: Process Control

    2. execfunction

      After execution of the child process is created with fork and parent process is the same program (but it is possible to perform different code branches), the child often have to call one of the exec function to execute another program. When a process call one of the exec function, the user code and data space of the process is completely replaced by a new program, the new program begins execution startup routine. Call exec does not create a new process, so the caller id of the process did not change before and after the exec.
      In fact, there are six at the beginning of the exec function, collectively exec function:

      #include <unistd.h>
      int execl(const char *path, const char *arg, ...);
      int execlp(const char *file, const char *arg, ...);
      int execle(const char *path, const char *arg, ..., char *const envp[]);
      int execv(const char *path, char *const argv[]);
      int execvp(const char *file, char *const argv[]);
      int execve(const char *path, char *const argv[], char *const envp[]);

      These functions if the call is successful then load the new program begins execution from boot code, not to return, if the call error -1 is returned, so only error exec function return value without success the return value.

    3. waitversuswaitpid

      Upon termination of a process will close all file descriptors, release the memory space allocated to the user, but it retains the PCB, which saved some kernel information: If the termination is normal exit status is preserved, if it is abnormally terminated then save the results in a signal which is the process to terminate. The parent process can call wait or waitpid obtain this information, and then completely removed in this process. We know the exit status of a process can be special variable $? View, because Shell is its parent process when it terminated Shell calls wait or waitpid to get its exit status while completely removed in this process with Shell.
      If a process has ended, but its parent process calls wait or waitpid it has not been cleaned, when the process state called zombies (Zombie) process. When any process is terminated just zombie process, under normal circumstances, zombies are immediately clean up the parent process.
      Zombie process can not be removed with a kill command, because the kill command is only used to terminate the process, and the zombie process has been terminated.

    #include <sys/types.h>
    #include <sys/wait.h>
    pid_t wait(int *status);
    pid_t waitpid(pid_t pid, int *status, int options);

    If the call was successful clean out the process id of the child is returned, if a call error -1 is returned. When calling parent process may wait or waitpid:

    • Blocking (if all its child processes are still running

    • Information terminate the process tape return immediately (if a child process has been terminated, is waiting for the parent to read its termination information)
    • Error return (if it does not have any child processes) immediately

    The difference between these two functions is:

    • If the parent process of all child processes are still running, will enable the parent process calls wait obstruction, but if you specify when calling waitpid WNOHANG in the options parameter allows the parent process does not block immediately return 0
    • wait wait for the child first stop, and wait waitpid can specify which sub-process by pid parameters

Source

timer source

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include <wait.h>
#include <ctime>
#include <iostream>
#include <cstring>
//程序假定输入完全正确,没有做异常处理
//mytime [-t number] 程序
using namespace std;
//调用系统时间
struct timeval time_start;
struct timeval time_end;

void printTime();

void newProcess(const char *child_process, char *argv[], double duration);

int main(int argc, char const *argv[])
{
    double duration = 0;
    char **arg;
    int step = 2;
    if (argc > 3 && (strcmp((char *)"-t", argv[1]) == 0)) //如果指定了运行时间
    {
        step = 4;
        duration = atof(argv[2]); //没有做异常处理
    }

    arg = new char *[argc - step + 1];
    for (int i = 0; i < argc - step; i++)
    {
        arg[i] = new char[100];
        strcpy(arg[i], argv[i + step]);
    }
    arg[argc - step] = NULL;

    newProcess(argv[step - 1], arg, duration);
    return 0;
}

void printTime()
{
    //用以记录进程运行的时间
    int time_use = 0;  // us
    int time_left = 0; // us
    int time_hour = 0, time_min = 0, time_sec = 0, time_ms = 0, time_us = 0;
    gettimeofday(&time_end, NULL);

    time_use = (time_end.tv_sec - time_start.tv_sec) * 1000000 + (time_end.tv_usec - time_start.tv_usec);
    time_hour = time_use / (60 * 60 * (int)pow(10, 6));
    time_left = time_use % (60 * 60 * (int)pow(10, 6));
    time_min = time_left / (60 * (int)pow(10, 6));
    time_left %= (60 * (int)pow(10, 6));
    time_sec = time_left / ((int)pow(10, 6));
    time_left %= ((int)pow(10, 6));
    time_ms = time_left / 1000;
    time_left %= 1000;
    time_us = time_left;
    printf("此程序运行的时间为:%d 小时, %d 分钟, %d 秒, %d 毫秒, %d 微秒\n", time_hour, time_min, time_sec, time_ms, time_us);
}

void newProcess(const char* child_process, char **argv, double duration)
{
    pid_t pid = fork();
    if (pid < 0) //出错
    {
        printf("创建子进程失败!");
        exit(1);
    }
    if (pid == 0) //子进程
    {
        execvp(child_process, argv);
    }
    else
    {
        if (abs(duration - 0) < 1e-6)
        {
            gettimeofday(&time_start, NULL);
            wait(NULL); //等待子进程结束
            printTime();
        }
        else
        {
            gettimeofday(&time_start, NULL);
            // printf("sleep: %lf\n", duration);
            waitpid(pid, NULL, WNOHANG);
            usleep(duration * 1000000); // sec to usec
            int kill_ret_val = kill(pid, SIGKILL);
            if (kill_ret_val == -1) // return -1, fail
            {
                printf("kill failed.\n");
                perror("kill");
            }
            else if (kill_ret_val == 0) // return 0, success
            {
                printf("process %d has been killed\n", pid);
            }
            printTime();
        }
    }
}

Test source code

#include <iostream>
#include <ctime>
#include <unistd.h>
using namespace std;
int main(int argc, char const *argv[])
{
    for(int n = 0; n < argc; n++)
    {
        printf("arg[%d]:%s\n",n, argv[n]);
    }
    sleep(5);
    return 0;
}

test

  1. Write your own test program

    1574351830016

  2. System testing program

    1574351915002

  3. The timer is added environment variables

    Here only a temporary variable changes.

    1574352171410

Windows

Create and manage parent-child processes under Windows compared to Linux on the api calls be difficult, but in fact in the use of management easier than Linux.

CreateProcess

#include <Windows.h>
BOOL CreateProcessA(
  LPCSTR                lpApplicationName,
  LPSTR                 lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL                  bInheritHandles,
  DWORD                 dwCreationFlags,
  LPVOID                lpEnvironment,
  LPCSTR                lpCurrentDirectory,
  LPSTARTUPINFOA        lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);

Source code implementation

timer program

// 进程管理.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <wchar.h>
#include <Windows.h>
#include <tchar.h>
using namespace std;


void printTime(SYSTEMTIME* start, SYSTEMTIME* end);
void newProcess(TCHAR* cWinDir, double duration);

int _tmain(int argc, TCHAR *argv[])
{
    TCHAR* cWinDir = new TCHAR[MAX_PATH];
    memset(cWinDir, sizeof(TCHAR) * MAX_PATH, 0);

    printf("argc:   %d\n", argc);

    int step = 1;
    double duration = 0;
    if (argc > 1)
    {
        if (argv[1][0] == TCHAR('-') && argv[1][1] == TCHAR('t') && argv[1][2] == TCHAR('\0'))
        {
            step = 3;
            duration = atof((char*)argv[2]);
        }
    }
    //printf("printf content start: %ls\n", argv[1]);
    int j = 0;
    for (int i = 0, h = 0; i < argc - step; i++)
    {
        wcscpy_s(cWinDir + j, MAX_PATH - j, argv[i + step]);
        for (h = 0; argv[i + step][h] != TCHAR('\0'); h++);
        j += h;
        cWinDir[j++] = ' ';
        //printf("%d : %d\n", i, j);
        //printf("printf content start: %ls\n", cWinDir);
    }
    cWinDir[j - 2] = TCHAR('\0');
    //printf("printf content start: %ls\n", cWinDir);

    newProcess(cWinDir,duration);

    return 0;
}


void printTime(SYSTEMTIME* start, SYSTEMTIME* end)
{
    int hours = end->wHour - start->wHour;
    int minutes = end->wMinute - start->wMinute;
    int seconds = end->wSecond - start->wSecond;
    int ms = end->wMilliseconds - start->wMilliseconds;
    if (ms < 0)
    {
        ms += 1000;
        seconds -= 1;
    }
    if (seconds < 0)
    {
        seconds += 60;
        minutes -= 1;
    }
    if (minutes < 0)
    {
        minutes += 60;
        hours -= 1;
    }
    //由于仅考虑在一天之内,不考虑小时会变成负数的情况
    printf("runtime: %02dhours %02dminutes %02dseconds %02dmilliseconds\n", hours, minutes, seconds, ms);
}

void newProcess(TCHAR* cWinDir, double duration)
{
    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
    

    SYSTEMTIME start_time, end_time;
    memset(&start_time, sizeof(SYSTEMTIME), 0);
    memset(&end_time, sizeof(SYSTEMTIME), 0);
    GetSystemTime(&start_time);

    if (CreateProcess(
        NULL,       //lpApplicationName.若为空,则lpCommandLine必须指定可执行程序
                    //若路径中存在空格,必须使用引号框定
        cWinDir,    //lpCommandLine
                    //若lpApplicationName为空,lpCommandLine长度不超过MAX_PATH
        NULL,       //指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承,进程安全性
        NULL,       //  如果lpProcessAttributes参数为空(NULL),那么句柄不能被继承。<同上>,线程安全性
        false,      //  指示新进程是否从调用进程处继承了句柄。句柄可继承性
        0,          //  指定附加的、用来控制优先类和进程的创建的标识符(优先级)
                    //  CREATE_NEW_CONSOLE  新控制台打开子进程
                    //  CREATE_SUSPENDED    子进程创建后挂起,直到调用ResumeThread函数
        NULL,       //  指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境。指向环境字符串
        NULL,       //  指定子进程的工作路径
        &si,        //  决定新进程的主窗体如何显示的STARTUPINFO结构体
        &pi         //  接收新进程的识别信息的PROCESS_INFORMATION结构体。进程线程以及句柄
    ))
    {
    }
    else
    {
        printf("CreateProcess failed (%d).\n", GetLastError());
        return;
    }


    //wait untill the child process exits
    if (abs(duration - 0) < 1e-6)
        WaitForSingleObject(pi.hProcess, INFINITE);//这里指定运行时间,单位毫秒
    else
        WaitForSingleObject(pi.hProcess, duration * 1000);

    GetSystemTime(&end_time);

    printTime(&start_time, &end_time);

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}

test program

#include <iostream>
#include <Windows.h>
using namespace std;
int main(int argc, char* argv[])
{
    for (int n = 0; n < argc; n++)
    {
        printf("arg[%d]:%s\n", n, argv[n]);
    }
    Sleep(5*1000);
    return 0;
}

test

  1. Write your own test program

    1574352549870

  2. System testing program

    1574352658762

  3. Add to the environment variables

    1574353167296

Reference material

Windows

Linux

Guess you like

Origin www.cnblogs.com/harrypotterjackson/p/11908825.html