Process Control 2 - Process Programming

Next up, let's write about process programming.

Get ID

With the command man get pid, we can get a detailed explanation of this function on the Linux terminal.

#include <sys/types.h>
#include <unistd.h>//header file

//Get the process ID
pid_t getpid(void)

//Get the parent process ID
pid_t getppid(void)

Let's look at the process ID through a piece of code

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    printf ("Current process id: %d\n",getpid());
    printf ("Current parent process id: %d\n",getppid());
    printf ("Current user process id: %d\n",getuid());

    while (1);
    return 0;
}


The output results will vary from terminal to terminal.

Process creation fork()

#include <unistd.h>

pid_t fork(void)//Create process

Function: Create subprocesses
fork() has a magic point that it is called once and returned twice. It may have three different return values:
1. In the parent process, fork returns the PID of the newly created child process.
2. In the sub-process, fork returns 0.
If an error occurs, fork returns a negative value.

When fork() is created successfully, there are two processes, each of which starts execution at fork().
Both processes execute the same code segment (text), but each has its own stack segment (stack), data segment (data), and heap.
The stack, data and heap of the child process are copied from the parent process, and the two processes only share code segments.

After fork(), you can't decide which process to execute first. What's the hidden danger?
Causes:
After fork(), it is not clear whether the parent process or the child process gets the CPU.
Harm:
Such bugs are hard to detect.
Measures:
If you need to ensure a specific execution sequence, you need to adopt some kind of synchronization technology (semaphores,file locks... )

fork() code:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    pid_t pid = fork();

    if (pid == -1) //Failure to create
    {
        perror ("fork");
        return -1;
    }

    if (pid > 0)
    {
        printf ("I am the father of the process. pid = %d\n",getpid());
    }

    if (pid == 0)
    {
        printf ("I am a sub-process. pid = %d\n",getpid());
    }

    return 0;
}
//So here comes the question...
int main()
{
    fork();
    fork();
    fork();
    //Several processes were created
    return 0;
}

int main()
{
    fork();
    fork() && fork() || fork();
    fork();
    //This creates several more processes
    return 0;
}

Let's mention the brother vfork() of fork(), which has almost the same function. The only difference is that vfork() needs exit() to exit.

exec function family

execl()

#include <unistd.h>

int execl(const char * path, const char* arg1,...)

Parameters:
Path: The name of the executed program (including the full path).
arg1 - argn: The command line parameter required by the executed program, including the program name. End with a null pointer (NULL).

execl code:

#include <stdio.h>
#include <unistd.h>


int main1()
{
    int  ret = execl("/bin/ls", "ls", NULL);
    if (ret == -1)
    {
        perror ("execl");
        return 0;
    }
    return 0;
}

execlp()
The only difference between execlp() and execl() is that the direct write execution file is not found in the current directory and will be looked up in the environment variable.
Linux is in the bin directory

int main()
{
    int  ret = execlp("/mnt/hgfs/share/0809/file", "./file", NULL);
    //Int RET = execlp (". / file", ". / file", NULL); the same path
    //Writing files directly finds files in the bin directory
    if (ret == -1)
    {
        perror ("execlp");
        return 0;
    }
    return 0;
}

execv()

#include <unistd.h>

int execv(const char * path, const char *argv[])

Parameters:
Path: The name of the executed program (including the full path).
argv []: An array of command line parameters required by the executed program.

Code:

int main()
{
    char *a[100] = {"./file", NULL};
    int  ret = execv("/mnt/hgfs/share/0809/file", a);
    //Int RET = execv (". / file", a); the same path
    //The latter parameters must be passed in as arrays
    if (ret == -1)
    {
        perror ("execlp");
        return 0;
    }
    return 0;
}

system()

#include <stdlib.h>

int system(const char* string)

Functions:
Call fork to generate a subprocess that calls / bin/sh -c string to execute the command represented by the parameter string

First of all, I like this function very much. It's powerful and can't be used in ink. The system("clear") that I usually like to use is to clear the screen, or to fill in the path of execution file in parentheses. We can even use it to make a pseudo-terminal, but there is a flaw, that is, some functions can't be realized.
Code:

int main()
{
    char str[100];
    while (1)
    {
        printf ("[root@localhost 0809]# ");
        fgets (str, 100, stdin);

        system (str);
    }
    return 0;
}

results of enforcement
It can be seen that it is not successful to exit the current directory after entering the pseudo terminal.

Termination of the process

Here exit, _exit is used to terminate the process. There is a distinct difference between the two.
_ exit: Stop the process directly, clear the memory it uses, and clear the contents of the buffer. (Like a cold-blooded agent who only seeks results but not processes)
exit: Before stopping the process, check the opening of the file and write the contents of the file buffer back to the file before stopping the process.

The next article will elaborate on the enmity and resentment between the son and father.

Keywords: Linux Programming

Added by neel_basu on Thu, 06 Jun 2019 01:28:20 +0300