C language foundation (14)

message queue

Message queue: By default, the sender puts the message after the previous message, and the receiver can specify which message to accept.
1. msgget: Create and open a message queue
int msgget(key_t key, int msgflg)
key value, this key value can create message pairs of different processes.
Parameter 1: key value; parameter 2: permission related to
ftok to obtain a specific key value.
key_t ftok(const char *pathname, int proj_id);
parameter 1: path; parameter 2: at least one char subcharacter (non-zero)
2. msgsnd sends a message to the message queue
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
parameter 1: message queue id; parameter 2: information structure of message sending; parameter 3: size(); parameter 4: blocking (0) or non-blocking (IPC_NOWAIT)
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
}
3. msgrcv accepts messages from the message queue
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg );
Useful information will be placed in the elements (arrays) of the msgp structure in the future.
msgflag is also blocking reading, which means that
msgtyp is always read when there is a message. Selecting 0 means that the first message is read first by default.
4. The message queue is maintained in the kernel. After it is used up, the
msgctl
parameter 1: qid; parameter 2: IPC_RMID; parameter: NULL (do not care about the detailed queue characteristics)

    题目:进程A 和 进程B,通过共享内存进行通信。
    PS:shmget注意是创建还是打开(共享内存)
//完成了发送端的程序
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define SIZE 200

struct msgbuf
{
        //消息的一个类型(>0)
        long mtype;
        //真实的消息
        char mtext[SIZE];
}; 

int main(void)
{
        key_t key = ftok(".", 'a');

        struct msgbuf msg = {0};
        struct msgbuf msg1 = {123, "computer"};

        int ret = -1;

        if (key < 0)
        {
                perror("ftok");

                exit(0);
        }
        else
        {
                printf("创建键值成功.\n");
        }

        //创建和打开一个消息队列
        int qid = msgget(key, IPC_CREAT | 0666);

        if (qid < 0)
        {
                perror("msgget");

                exit(0);
        }

        printf("打开了一个消息队列qid = %d.\n", qid);

        while (1)
        {
                //填充结构体
                msg.mtype = getpid();
                printf("输入消息:\n");
                fgets(msg.mtext, SIZE, stdin);
                //添加消息到消息队列,进行排队
                ret = msgsnd(qid, &msg1, SIZE, 0);
                if (ret < 0)
                {
                        perror("msgsnd1");

                        exit(0);
                }

                ret = msgsnd(qid, &msg, SIZE, 0);
                if (ret < 0)
                {
                        perror("msgsnd2");

                        exit(0);
                }
                //结束我们进程
                if (strncmp(msg.mtext, "quit", 4) == 0)
                        break;

        }




        return 0;
}

Shared memory

Shared memory: Find a piece of memory from the real physical space and map it to our virtual memory. The mapped memory between different processes thinks that this memory is its own, which involves synchronization.
1. Get the memory of a certain size from the physical address
int shmget(key_t key, size_t size, int shmflg);
parameter 1: special key value parameter 2: get memory size 3: memory permission
PS: ipcs -m can specifically view shared memory Details.
2. Delete shared memory
shmctl
3. Create shared
void *shmat(int shmid, const void *shmaddr, int shmflg);
parameter 2: shmaddr == NULL, indicating that the operating system automatically allocates an unused and safe address.
Parameter 3shmflag: select IPC_RDONLY read-only mode, guess if 0 is readable and writable?
4. Disconnect the mapping relationship between the shared memory and the process in which it is located.
int shmdt(const void *shmaddr);
parameter: it contains the valid, legal and unused addresses mapped in the process in the past


#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>


#define SIZE 2048

int main(void)
{
#if 1
        int shmid = 0;
        char *ptr = NULL;
        char flag[] = "i am a flag!";
        char buf[1024] = {0};

        pid_t pid;

        //创建共享内存
        shmid = shmget(IPC_PRIVATE, SIZE, 0666);

        if (shmid < 0)
        {
                perror("shmget");

                exit(0);
        }
        else
        {
                printf("创建申请的shm_memory:%d.\n", shmid);
        }
        //查看共享内存使用情况
//      system("ipcs -m");

        //创建进程
        pid = fork();

        if (pid < 0)
        {
                perror("fork");

                exit(0);
        }

        if (pid == 0)
        {
                // 子进程
                //映射内存
                ptr = shmat(shmid, NULL, 0);
                if (ptr == (void *)-1)
                {
                        perror("子进程shmat");
                        exit(0);
                }
                else
                {
                        printf("子进程映射的地址:%p.\n", ptr);
                }
                //读父进程的flag是否写入
                while (strncmp(ptr, flag, strlen(flag)))
                {
                        printf("子进程等有效数据\n");
                        sleep(5);
                }
                //读取父进程有效数据
//              strcpy(buf, ptr+strlen(flag));
//              printf("子进程得到有效数据[%s].\n", buf);
                struct infor
                {
                        char name[20];
                        int age;
                        int money;
                }s = {0};
                //接受结构体信息
                s = *((struct infor *)(ptr+strlen(flag)));
                printf("名字:%s, 年龄:%d, 存款:%d.\n", s.name, s.age, s.money);

                //子进程分离共享内存
                if (shmdt(ptr) < 0)
                {
                        perror("子进程ptr");
                        exit(0);
                }
                else
                        printf("子进程分离OK!\n");
//              system("ipcs -m");
                //删除共享内存
                if (shmctl(shmid, IPC_RMID, NULL) < 0)
                {
                        perror("子进程删除内存错误\n");
                        exit(0);
                }

                printf("子进程删除成功\n");

        }

        if (pid > 0)
        {
                // 父进程
                //映射内存
                ptr = shmat(shmid, NULL, 0);
                if (ptr == (void *)-1)
                {
                        perror("父进程shmat");
                        exit(0);
                }
                else
                {
                        printf("父进程映射的地址:%p.\n", ptr);
                }

                printf("父进程写东西:\n");
                //写正式内容
//              fgets(buf, SIZE, stdin);
                struct infor
                {
                        char name[20];
                        int age;
                        int money;
                }s = {"小丽", 16,  500000000};                
//              strncpy(ptr+strlen(flag), buf, strlen(buf));
                memcpy((struct infor*)(ptr+strlen(flag)), &s, sizeof(s));
                strncpy(ptr, flag, strlen(flag));
                //父进程分离共享内存
                if (shmdt(ptr) < 0)
                {
                        perror("父进程ptr");
                        exit(0);
                }
                else
                        printf("父进程分离OK!\n");
//              system("ipcs -m");
                //父进程等待子进程结束
                waitpid(pid, NULL, 0);

                printf("所犯的罪过一切结束了\n");             
        }

#endif  
/*  
        shmctl(5570615, IPC_RMID, NULL);
        shmctl(5603388, IPC_RMID, NULL);
        shmctl(5636157, IPC_RMID, NULL);

        system("ipcs -m");
*/      
//      shmctl(shmid, IPC_RMID, NULL);
        return 0;
}

Signal

Signal: It is an asynchronous communication method, and the communication content is limited.
Signal: It is a series of int data programmed in advance.
Signal generation method:
(1) hardware generation
(2) to meet certain software requirements
(3) hardware exception signal
(4) processing method of kill -9
signal:
to whom Yes, who handles
(1) default processing
(2) capture processing (signal is bound to a function)
(3) ignore processing
common signals: (path: /usr/include/bits/signum.h)
(1) SIGINT 2 It is the usual ctrl+c
(2) SIGABRT 6 program is terminated abnormally
(3) SIGKILL 9 kills a process (ultimate method)
(4) SIGSEGV 11 invalid memory access
(5) SIGALRM 14 alarm signal
(6) SIGCHLD 17 sub The signal sent when the process ends
(7) SIGSTOP 19 Kill (pause) a process ctrl+\
1. Install the signal function
raise to send a signal to the current process

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>

int main(void)
{
        pid_t pid;

        int ret = -1;

        pid = fork();

        if (pid < 0)
        {
                perror("fork");
                exit(0);
        }       

        if (pid == 0)
        {
                sleep(1);
                //子进程
                printf("子进程等待别的信号唤醒自己pid = %d:\n", getpid());
                raise(SIGSTOP);
                printf("子进程醒了.\n");
                exit(0);
        }

        if (pid > 0)
        {
                // 父进程
//              sleep(3);
                if (waitpid(pid, NULL, WNOHANG) == 0)
                {
                        //
                        if ((ret = kill(pid, SIGCONT)) == 0)
                        {
                                printf("父进程杀了子进程pid = %d.\n", pid);
                        }
                }

                waitpid(pid, NULL, 0);

                printf("一切结束.\n");
        }





        //一个进程发两个信号 
//      while (1);

/*
//      int i = 4 / 0;
        int i;
        printf("i = %d.\n", i);

        while (1);
*/



        return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325810494&siteId=291194637