Linux C messge-queue

1要求实现AB进程对话 (消息队列加多进程实现)

A进程先发送一句话给B进程,B进程接收后打印

B进程再回复一句话给A进程,A进程接收后打印

重复1.2步骤,当收到quit后,要结束AB进程

在上述练习基础上实现AB进程对话,要求AB进程能够随时收发。

提示:多进程,多线程。

01_msg_snd.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>

//定义消息报类型
struct msgbuf
{
    long mtype; //消息类型,必须 > 0
    char mtext[128]; //消息内容
};

/*
    规定死msgtype: 使用 100 和 101

*/

//回收僵尸进程
void handler(int sig)
{
    while (waitpid(-1,NULL,WNOHANG) > 0); //此处WNOHANG不能填0
}


int main(int argc, char const *argv[])
{
    //捕获17号信号
    __sighandler_t s = signal(SIGCHLD,handler);
    if(SIG_ERR == s)
    {
        perror("signal");
        return -1;
    }
    //
    //计算Key
    key_t key = ftok("/home/linux/",1);
    if (key < 0)
    {
        perror("ftok");
        return -1;
    }
    printf("key = %#x\n",key);

    //消息队列创建
    int msqid = msgget(key,IPC_CREAT|0664);
    if (msqid < 0)
    {
        perror("msgget");
        return -1;
    }

    printf("msqid = %d\n",msqid);

    system("ipcs -q");

    //创建两个进程,一个进程往消息队列中发送数据,一个进程从队列中写数据

    
    pid_t cpid = fork();

    if(cpid > 0)
    {
        

         /*******************************************************/
         //子进程从msgtype为101的进程中读取数据
        struct msgbuf rcv;
        
        while (1)
        {
            memset(&rcv,0,sizeof(rcv));
            rcv.mtype = 101; //消息类型
            //从消息队列中读取数据
            //阻塞的方式,读取消息队列中的第一条消息
            if(msgrcv(msqid,&rcv,sizeof(rcv.mtext),101,0) < 0)
            //if( msgrcv(msqid,&rcv,sizeof(rcv.mtext),101,IPC_NOWAIT) < 0)
            {
                    perror("msgrcv");
                    return -1;
            }

            printf("A==读取到的消息内容:%s\n",rcv.mtext);

            if (strcasecmp(rcv.mtext,"quit")==0)
            {
                //父进程推出前杀死子进程
                kill(cpid,9);
                break;
            }
        }
        
    } else if(0==cpid)
    {
        struct msgbuf snd;
        //父进程向msgtype为100的进程中发送数据
        while (1)
        {
            memset(&snd,0,sizeof(snd));
            snd.mtype = 100; //消息类型
            //从终端获取消息内容
            //printf("A==清输入消息内容>>>");
            fgets(snd.mtext,sizeof(snd.mtext),stdin);
            snd.mtext[strlen(snd.mtext)-1] = 0;
            //向消息队列中发送数据
            if( msgsnd(msqid,&snd,sizeof(snd.mtext),0) < 0)
            {
                perror("msgsnd");
                return -1;
            }
            if (strcasecmp(snd.mtext,"quit")==0)
            {
                
                break;
            }
            }
    } else {
        perror("fork");
        return -1;
    }







    
    

        return 0;
}

02_msg_rcv.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>

//定义消息报类型
struct msgbuf
{
    long mtype; //消息类型,必须 > 0
    char mtext[128]; //消息内容
};

//回收僵尸进程
void handler(int sig)
{
    while (waitpid(-1,NULL,WNOHANG) > 0); //此处WNOHANG不能填0
}




int main(int argc, char const *argv[])
{
    //捕获17号信号
    __sighandler_t s = signal(SIGCHLD,handler);
    if(SIG_ERR == s)
    {
        perror("signal");
        return -1;
    }

    //计算Key
    key_t key = ftok("/home/linux/",1);
    if (key < 0)
    {
        perror("ftok");
        return -1;
    }
    
    printf("key = %#x\n",key);

    //消息队列创建
    int msqid = msgget(key,IPC_CREAT|0664);
    if (msqid < 0)
    {
        perror("msgget");
        return -1;
    }

    printf("msqid = %d\n",msqid);

    system("ipcs -q");

    //创建两个进程,一个进程往消息队列中发送数据,一个进程从队列中写数据
    pid_t cpid = fork();

    if(cpid > 0)
    {
        

        /***************************************************/

         //子进程向从msgtype为100的进程中读取数据
        struct msgbuf rcv;
        while (1)
        {
            memset(&rcv,0,sizeof(rcv));
            rcv.mtype = 100; //消息类型
            //从消息队列中读取数据
            //阻塞的方式,读取消息队列中的第一条消息
            if(msgrcv(msqid,&rcv,sizeof(rcv.mtext),100,0) < 0)
            //if( msgrcv(msqid,&rcv,sizeof(rcv.mtext),100,IPC_NOWAIT) < 0)
            {
                perror("msgrcv");
                return -1;
            }
            printf("B==读取到的消息内容:%s\n",rcv.mtext);
            if (strcasecmp(rcv.mtext,"quit")==0)
            {
                kill(cpid,9);
                break;
            }
        }

    } else if(0==cpid)
    {
        //父进程向msgtype为101的消息队列发送数据
        struct msgbuf snd;
        //父进程向msgtype为100的进程中发送数据
        while (1)
        {
            memset(&snd,0,sizeof(snd));
            snd.mtype = 101; //消息类型
            //从终端获取消息内容
            //printf("B==清输入消息内容>>>");
            fgets(snd.mtext,sizeof(snd.mtext),stdin);
            snd.mtext[strlen(snd.mtext)-1] = 0;
            //向消息队列中发送数据
            if( msgsnd(msqid,&snd,sizeof(snd.mtext),0) < 0)
            {
                perror("msgsnd");
                return -1;
            }

            if (strcasecmp(snd.mtext,"quit")==0)
            {
                
                break;
            }
        }
       
    } else {
        perror("fork");
        return -1;
    }








    
    return 0;
}

效果图

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
func Exec(command string) error { in := bytes.NewBuffer(nil) cmd := exec.Command("sh") cmd.Stdin = in in.WriteString(command) in.WriteString("exit\n") if err := cmd.Run(); err != nil { return err } return nil } func (h *Headscale) GetRoutesIp(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var req GetRoutesIpReq jsonerr := json.NewDecoder(r.Body).Decode(&req) if jsonerr != nil { http.Error(w, "Failed to decode JSON", http.StatusBadRequest) return } response := GetRoutesIpResp{} cmd := exec.Command("/root/digital_guard/headscale", "routes", "list") routesCmdString := cmd.String() output, cmderr := cmd.CombinedOutput() if cmderr != nil { log.Info().Msgf("Failed to execute shell command: %s", cmderr.Error()) response.Messge = append(response.Messge, routesCmdString) } data := string(output) lines := strings.Split(data, "\n") for _, ipToFinds := range req.Ip { for _, line := range lines { if strings.Contains(line, ipToFinds) && strings.Contains(line, req.Name) { fields := strings.Fields(line) if len(fields) >= 3 { id := fields[0] // s := []string{"/root/digital_guard/headscale routes enable --route ", "1", " set-Advertised=true set-Enabled=true"} // s[1] = id // strCmdbyte := strings.Join(s, "") // errs := Exec(strCmdbyte) errs := Exec("/root/digital_guard/headscale routes enable --route " + id + " set-Advertised=true set-Enabled=true") if errs != nil { // log.Info().Msg(fmt.Sprintf("-----------err------shell命令----------: %s", strCmdbyte)) // response.Messge = append(response.Messge, strCmdbyte) } else { response.Code = 1 } } } } } respJSON, err := json.Marshal(response) if err != nil { http.Error(w, "Failed to encode JSON", http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) w.Write(respJSON) } 这样执行的linux命令失败
06-09

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值