Linux process and process communication programming (2)

What makes the desert beautiful is that somewhere it hides a well.

The desert is beautiful because there is a well hidden somewhere in it.

Linux process and process communication programming (2)

  • interprocess communication
    • 1. Pipeline communication
      • (1) Famous pipeline
        • mkfifo
        • 21write.c , 21read.c code
      • (2) Anonymous pipe
        • 20.c code
    • 2. Signal communication
      • (1) Signal sending
        • raise
        • 22.1.c code
        • kill
        • 22-2.c, 22-3.c code
        • alarm
        • 22-4.c code
      • (2) Signal reception
        • use pause
        • 22-5.c code
      • (3) Signal processing
        • use signal
        • 22-6.c code
    • 3. Shared memory
      • Create shared memory
        • shmget
        • 24-1.c code
        • shmat
        • shmdt
        • shmctl

Interprocess communication

1. Pipeline communication

Process A and process B belong to the application layer and cannot communicate directly

Pipes are used for communication between them, pipes exist in the kernel

Regardless of whether it is named or unnamed, as long as there is no content in the pipeline, the use of the read function will be blocked

(1) Famous pipeline

Can be used for any two processes

Related programs 21write.c , 21read.c

mkfifo

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


You have to write and read at the same time to read

21write.c, 21read.c code

21write.c

#include <stdio.h> //for main function
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <unistd.h> //for close, read, write, fork
int main(int argc, char *argv[])
{<!-- -->
    char buf[32] = {<!-- -->0};
    int fd;
    int ret;

    if (argc < 2)
    {<!-- -->
        printf("Input fifo file name:\\
"); //Input parameters are too few, give a prompt
        printf("argc:%d\\
", argc);
    }
 
    else if (argc = 2)
    {<!-- -->
        printf("argc:%d\\
", argc);
        if (access(argv[1], F_OK) == -1)
        {<!-- --> // access is used to determine whether there is a fifo file for keyboard input
            ret = mkfifo(argv[1], 0666); //If it does not exist, create a pipeline file
            if (ret == -1)
            {<!-- -->
                printf("Error");
            }
            else
                printf("The pipeline is built");
        }

        fd = open(argv[1], O_WRONLY);
        write(fd, "hello111", 8);
        close(fd);
    }
}

21read.c

#include <stdio.h> //for main function
#include <stdlib.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h> //for close, read, write, fork
int main(int argc, char *argv[])
{<!-- -->
    char buf[32] = {<!-- -->0};

    int fd;
    int ret;

    if (argc < 2)
    {<!-- -->
        printf("Input the file name of fifo:\\
"); //There are too few input parameters, just give a prompt
    }

    else if (argc = 2)
    {<!-- -->
        
        fd = open(argv[1], O_RDONLY);
        read(fd, buf, 32);
        printf("buf:%s\\
", buf);
        close(fd);
    }
    
}

(2) Nameless pipe

for parent and child processes

Related program 20.c

The unnamed pipe is created before the child process

If the parent process is blocked, the program will always be stuck

When the parent process writes, the child process can read it

20.c code

//Unnamed pipe

#include <stdio.h> //for main function
#include <stdlib.h>
#include <sys/types.h> //for pid_t
#include <sys/stat.h>
#include <sys/wait.h>

#include <unistd.h> //for close, read, write, fork

int main() //No parameters
{<!-- -->
    char buf[32]={<!-- -->0};
    
    int fd[2]; //Define the descriptors at both ends of the pipeline, there are two
    pipe(fd); //create pipeline
    printf("fd[0]:%d\\
",fd[0]); // print fd at the reading end
    printf("fd[1]:%d\\
", fd[1]); //print the fd on the write side

    pid_t pid; //Define a pid to receive the return value of fork
    pid = fork();

    if (pid < 0)
    {<!-- -->
        printf("Failed to create");
    }

    // parent process
    if (pid > 0)
    {<!-- -->
        write(fd[1],"hello",5);
    }

    //child process
    if (pid == 0)
    {<!-- -->
        close(fd[1]); //Close the write terminal, only read
        read(fd[0],buf,32);
        printf("buf:%s\\
",buf);
        close(fd[0]);
    }
}

2. Signal communication

Which signal to use, you can check it online

(1) Signal sending

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

raise

used to signal oneself

Related procedure 22.1.c

22.1.c code

#include <stdio.h> //for main function
#include <stdlib.h>

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
int main()
{<!-- -->
    printf("raise before\\
");

    raise(9); // raise means that the signal sent by oneself cannot be captured, and the 9 in it means to terminate the process
    
    printf("raise after\\
");
}

kill

It is used to kill the process, which has the same effect as the kill command

Related Procedure 22-2.c

Use 22-2.c to kill the process of 22-3.c

22-2.c, 22-3.c code

22-2.c

#include <stdio.h> //for main function
#include <stdlib.h>

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

int main(int argc, char *argv[])
{<!-- -->
    pid_t pid;
    int sig;

    if(argc<3){<!-- -->
        printf("Enter the process pid and signal type\\
");
    }

    sig=atoi(argv[2]);
    pid = atoi(argv[1]);
    kill(pid,sig);
}

22-3.c

#include <stdio.h> //for main function
#include <stdlib.h>

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
int main()
{<!-- -->
    while(1){<!-- -->
        sleep(1);
        printf("hh\\
");
    }
}

alarm

Similar to setting an alarm clock, kill the process when the time is up

Related program 22-4.c

22-4.c code

#include <stdio.h> //for main function
#include <stdlib.h>

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
int main()
{<!-- -->
    int i;
    alarm(4); //indicates to kill the process at 4s

    while (1)
    {<!-- -->
        sleep(1);
        i + + ;
        printf("i:%d\\
",i);
    }
    
}

(2) Signal reception

A process takes a long time to receive a signal

For example, use while (1), sleep (x) (running in x seconds), pause (sleep all the time)

When the process is running, press ctrl + c, enter kill, and the process can receive these signals

use pause

It is used to let the process run halfway and enter the dormant state, and it will remain dormant, and exit with signal or ctrl + c

Related procedure 22-5.c

22-5.c code

#include <stdio.h> //for main function
#include <stdlib.h>

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
int main()
{<!-- -->
    printf("before pause\\
");

    pause(); // pause means enter sleep

    printf("after pause\\
");
}

(3) Signal processing

default (terminate) , ignore , capture

Use signal

Related program 22-6.c

//header file
#include <signal.h>

default

signal(SIGINT,SIG_DFL);
//SIGINT means ctrl + c, SIG_DFL means to execute the default operation of ctrl + c, which is to terminate


neglect

signal(SIGINT,SIG_IGN);
//SIGINT means ctrl + c, SIG_IGN means ignore ctrl + c signal

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture Save it and upload directly (img-ZZaWcKtl-1679546479431)(D:\md picture\1667749555858.png)]
capture

signal(SIGINT,myfun);
//Catch the signal SIGINT, and then execute the code in myfun
//For example, press ctrl + c to execute another cycle

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture Save it and upload directly (img-jC7yhIah-1679546510509)(D:\md picture\1667750409322.png)]

22-6.c code

#include <stdio.h> //for main function
#include <stdlib.h>

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

// void fun(int sig){
// if(sig==SIGINT){<!-- -->
// while (1)
// {<!-- -->
// printf("hei hei\\
");
// sleep(2);
// }
// }
// }

int main()
{<!-- -->
    // signal(SIGINT,SIG_IGN); //ignore
    // signal(SIGINT, SIG_DFL); //default
    // signal(SIGINT, fun); // execute new function
    while (1)
    {<!-- -->
        printf("hh\\
");
        sleep(2);
    }
}

3. Shared memory

for inter-process communication

Create shared memory

shmget

Related procedure 24-1.c

//header file
#include <sys/ipc.h>
#include <sys/shm.h>

Use macros as key values

Use ftok return value as key value

24-1.c code

//Create shared memory, use macro as key value

#include <stdio.h> //for main function
#include <stdlib.h>

#include <sys/ipc.h>//for shmget
#include <sys/shm.h>

#include <sys/types.h>

int main()
{<!-- -->
    int id;

    id = shmget(IPC_PRIVATE, 1024, 0777); // IPC_PRIVATE uses macros as key values

    if (id < 0)
    {<!-- -->
        printf("Failed to create shared memory\\
");
    }
    else
        printf("id:%d\\
", id);
    
}

shmat

Used to map shared memory in the kernel to user space

shmdt

Delete the address of the shared memory mapping

shmctl

Delete the shared memory address in the kernel