C语言:进程间通信

管道

又内核提供,单工,自同步机制。使用广泛。(管道必须凑齐读写双方才能够运行。)

匿名管道

/home/qt/c/linux_c/ipc/pipe

看不到管道的名称,适合有亲缘关系的进程通信。

pipe.c

       int pipe(int fildes[2]);
 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>#define BUFSIZE 1024
int main()
{pid_t pid;int ret;int pd[2];char buf[BUFSIZE];int len;ret = pipe(pd); // 0是读,1是写if(ret<0){perror("pipe()");exit(1);}pid = fork();if(pid == 0){//child read   close(pd[1]);puts("Child Begin");len = read(pd[0],buf,BUFSIZE); //如果父进程不写,那么会阻塞等待write(1,buf,len);close(pd[0]);puts("Child End");exit(1);puts("Exit");}else if(pid >0){sleep(1);// parent writeclose(pd[0]);write(pd[1],"Hello\n",6);close(pd[1]);
//        wait(NULL);exit(1);}return 0;
}

player.c 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>#define BUFSIZE 1024
int main()
{pid_t pid;int ret;int pd[2];char buf[BUFSIZE];int len;ret = pipe(pd); // 0是读,1是写if(ret<0){perror("pipe()");exit(1);}pid = fork();if(pid == 0){//child read   close(pd[1]);dup2(pd[0],0); //将管道重定向到标准输入。close(pd[0]);int fd = open("/dev/null",O_RDWR);dup2(fd,1);//关闭文件描述符1,然后文件描述符1执行 /dev/nulldup2(fd,2);execl("usr/bin/mpg123","mpg123","-",NULL);perror("excel");exit(0);}else if(pid >0){close(pd[0]);//父进程从网上收数据,在管道中写。close(pd[1]);wait(NULL);exit(0);}return 0;
}

命名管道

mkfifo namedfifo可以创建一个命名管道,文件类型为P

可以看到管道的名称,适合非亲缘关系的进程通信。

mkfifo

       int mkfifo(const char *pathname, mode_t mode);
 

XSI ->SysV

XSI(System Interface and Headers),代表一种Unix系统的标准 XSI IPC,依托标识符和键来实现的,如同管道靠文件描述符来实现一样。包含了三种通信机制:消息队列,信号量,共享内存。

ipcs命令:可以看到 消息队列,信号量数组,共享内存的信息。

key:ftok();拿到同一个key值。

       key_t ftok(const char *pathname, int proj_id); //hash的原串+杂志。

xxxget xxxop xxxctl
xxx -> msg  sem shm

 消息队列

消息队列有缓存数据的能力,通过ulimit -a查看

主动端:先发包的一方。
被动端:先收包的一方。

/home/qt/c/linux_c/ipc/xsi/msg/basic

       int msgget(key_t key, int msgflg);
       int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
       ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
                      int msgflg);
       int msgctl(int msqid, int cmd, struct msqid_ds *buf);

proto.h
#ifndef PROTO_H
#define PROTO_H#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>#define KEYPATH "/etc/services"
#define KEYPROJ 'a'
#define NAMESIZE 1024struct msg_st
{long mtype;char name[NAMESIZE];int math;int chinese;};#endif 
snder.c
#include <stdlib.h>
#include <stdio.h>
#include "proto.h"int main()
{key_t key;key = ftok(KEYPATH,KEYPROJ);if(key <0){perror("ftok()");exit(1);}int msgid;msgid = msgget(key,0);if(msgid <0){perror("msgget");exit(1);}struct msg_st sbuf;sbuf.mtype = 1;sprintf(sbuf.name,"%s","hello msg");sbuf.math = rand()%100;sbuf.chinese = rand()%100;int len;len = msgsnd(msgid,&sbuf,sizeof(sbuf) - sizeof(long),0);if(len <0){perror("msgsnd()");exit(1);}puts("OK!");
//    msgctl();return 0;
}
recv.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>#include "proto.h"int main()
{key_t key;key = ftok(KEYPATH,KEYPROJ);if(key <0){perror("ftok()");}int msgid;msgid = msgget(key,IPC_CREAT|0600 );if(msgid<0){perror("msgget");}struct msg_st rbuf;int len;while(1){len = msgrcv(msgid,&rbuf,sizeof(rbuf)-sizeof(long),0,0 );if(len <0){perror("msgrcv");}printf("NAME  = %s \n",rbuf.name);printf("MATH  = %d \n",rbuf.math);printf("CHINESE = %d \n",rbuf.chinese);}msgctl(msgid,IPC_RMID,NULL);return 0;
}

命令:ipcrm 删除上述程序中产生的消息队列。ipc -q (msqid号)

消息队列ftp协议

#ifndef PROTO_H
#define PROTO_H#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>#define KEYPATH "/etc/services"
#define KEYPROJ 'a'
#define PATHSIZE 1024
#define DATASIZE 1024
enum
{MSG_PATH =1,MSG_DATA,MSG_EOT
}typedef struct msg_path_st
{long mtype; //must be MSG_PATHchar path[PATHSIZE]; //ASCII带尾0的串}msg_path_t;typedef struct msg_data_st
{long mtype;char data[DATAMAX];int datalen;}msg_data_t;typedef struct msg_eot_st
{long mtype;
}msg_eot_t;union msg_s2c_un
{long mtype; //提取公因子。msg_data_t datamsg;msg_eot_t  eotmsg;
};#endif
#ifndef PROTO_H
#define PROTO_H#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>#define KEYPATH "/etc/services"
#define KEYPROJ 'a'
#define PATHSIZE 1024
#define DATASIZE 1024
enum
{MSG_PATH =1,MSG_DATA,MSG_EOT
}typedef struct msg_path_st
{long mtype; //must be MSG_PATHchar path[PATHSIZE]; //ASCII带尾0的串}msg_path_t;typedef struct msg_s2c_st
{long mtype; /* 用MSG_DATA或者MSG_EOT进行判断*/char data[DATAMAX];int datalen;/*datalen >0 :data包datalen =0 :eot包*/
}msg_data_t;#endif

信号量

路径:c/linux_c/ipc/xsi/sem,P(取资源)V(还资源)操作。

       int semget(key_t key, int nsems, int semflg);
   int semop(int semid, struct sembuf *sops, size_t nsops);
       int semtimedop(int semid, struct sembuf *sops, size_t nsops,
                      const struct timespec *timeout);
       int semctl(int semid, int semnum, int cmd, ...);
 

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>#define FILENAME  "/tmp/out"
#define PROCNUM (10)static int semid;static void P()
{struct sembuf op;op.sem_num = 0;op.sem_op = -1;op.sem_flg = 0;int ret;ret = semop(semid,&op,1);while(ret<0){if(errno != EINTR || errno != EAGAIN){perror("semop");exit(1);}}}static void V()
{struct sembuf op;int ret;op.sem_num = 0;op.sem_op = 1;op.sem_flg = 0;ret = semop(semid,&op,1);if(ret<0){perror("semop");exit(1);}
}void func_add(void);int main()
{pid_t pid;int i,j,mark;int err; semid = semget(IPC_PRIVATE,1,0600);   //匿名ipc,用于父子进程通信if(semid <0){perror("semget");exit(1);}int ret;ret = semctl(semid,0,SETVAL,1);//设置数组0下标的值为1.if(ret<0){perror("semctl");exit(1);}for(i =0;i<PROCNUM;i++){pid = fork();if(pid ==0){func_add();exit(0);}if(pid >0){}}for(i=0;i<PROCNUM;i++){wait(NULL);}semctl(semid,0,IPC_RMID);return 0;
}void func_add()
{FILE*fp;char line_buf[1024];int len_size = 1024;puts("Begin");fp = fopen(FILENAME,"r+");int fd = fileno(fp);P();fgets(line_buf,len_size,fp);fseek(fp,0,SEEK_SET);sleep(1);fprintf(fp,"%d \n",atoi(line_buf)+1);fflush(fp);V();fclose(fp);puts("End");}  

共享内存

       int shmget(key_t key, size_t size, int shmflg);
       void *shmat(int shmid, const void *shmaddr, int shmflg);
       int shmdt(const void *shmaddr);
       int shmctl(int shmid, int cmd, struct shmid_ds *buf);
 

#include  <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>#define MEMSIZE 1024int main(int argc,char*argv[])
{int shmid;pid_t pid;shmid = shmget(IPC_PRIVATE,MEMSIZE,0600);if(shmid<0){perror("shmget");exit(1);}pid = fork();if(pid==0){//child writechar *ptr;ptr = shmat(shmid,NULL,0); //共享内存映射。if(ptr == (void*)-1){perror("shmat");exit(1);}strcpy(ptr,"hello");shmdt(ptr); //解除映射exit(0);}if(pid >0){wait(NULL);//parent readchar *ptr;ptr = shmat(shmid,NULL,0);if(ptr == (void*)-1){perror("shmat");exit(1);}puts(ptr);shmdt(ptr);shmctl(shmid,IPC_RMID,NULL);exit(0);}return 0;
}

网络套接字

网络套接字又称:socket。讨论:跨主机传输要注意的问题。

大小端问题

字节序经常被分为两类:

1. Big-Endian(大端):高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

2.Little-Endian(小端):低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

对于数据 0x12345678,假设从地址0x4000开始存放,在大端和小端模式下,存放的位置分别为:

内存地址    小端模式    大端模式
0x4003    0x12    0x78
0x4002    0x34    0x56
0x4001    0x56    0x34
0x4000    0x78    0x12
采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。

小端存储后:0x78563412  大端存储后:0x12345678

字节序问题

TCP/IP各层协议将字节序定义为Big-Endian,
因此TCP/IP协议中使用的字节序通常称之为网络字节序。

通常我们说的主机序(Host Order)就是遵循Little-Endian规则

就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。

主机字节序:host

网络字节序:network 

相互转换:_to_ _ :htons,htonl,ntohs,ntohl

数据对齐问题

结构体在传输数据时会进行内存对齐。解决方式是不进行数据对齐。

类型长度问题

long类型的大小没有指定,char有咩有符号也没有定义。int的大小在16位和32位长度不一样。

解决:int32_t ,uint32_t ,int64_t使用特定的数据类型。

SOCKET

socket是对TCP/IP协议的封装,它的出现只是使得程序员更方便地使用TCP/IP协议栈而已。socket本身并不是协议,它是应用层与TCP/IP协议族通信的中间软件抽象层,是一组调用接口(TCP/IP网络的API函数)

“TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口。
  这个就像操作系统会提供标准的编程接口,比如win32编程接口一样。
  TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口

        int socket(int domain, int type, int protocol);

报式套接字

被动端:

1、取得socket
2、给socket取得地址
3、收/发消息
4、关闭socket

主动端:

1、取得socket
2、给socket取得地址(可以省略)
3、收/发消息
4、关闭socket

socket();
bind();
sendto();
recvform();
inet_pton();
inet_ntop();
getsockopt();
setsockopt();
 

netstat -anu 查看报式套接字的信息。

path:  c/linux_c/ipc/socket/udp/basic

定长实现

proto.h
#ifndef PROTO_H
#define PROTO_H#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>#define IPSTRSIZE 128
#define NAMESIZE 11
#define RECVPORT "1989" //选择超过1024以上的端口struct msg_st
{uint8_t  name[NAMESIZE]; // 8位相当于charuint32_t math;uint32_t  chinese;
}__attribute__((packed)); //告诉编译器结构体不用对齐#endif 
recv.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "proto.h"int main()
{int sd;sd  = socket(AF_INET,SOCK_DGRAM,0); //0代表默认的协议 IPPROTO_UDPif(sd <0){perror("socket");exit(1);}int ret;struct sockaddr_in laddr;laddr.sin_family = AF_INET;laddr.sin_port = htons(atoi(RECVPORT)); // 端口号 host to network 主机序列转为网络序列inet_pton(AF_INET,"0.0.0.0",&laddr.sin_addr);  //ip地址 需要转为大整数ret = bind(sd,(void *)&laddr,sizeof(laddr)); //不同的协议族绑定的地址是不一样的,需要man 7 ip 查看。if(ret<0 ){perror("bind()");exit(1);}struct msg_st rbuf;struct sockaddr_in raddr;socklen_t raddr_len;char ipstr[IPSTRSIZE];/* raddr_len如果不初始化,那么第一次地址会出错,后续不会*/raddr_len = sizeof(raddr);while(1){recvfrom(sd,&rbuf,sizeof(rbuf),0,(void *)&raddr,&raddr_len); //recv是流式套接字,recvform是报式,需要记录对端的地址。inet_ntop(AF_INET,&raddr.sin_addr,ipstr,IPSTRSIZE);printf("---MSSSAGE FORM %s:%d---\n",ipstr, ntohs(raddr.sin_port) ); //大整数转点分式printf("NAME = %s\n",rbuf.name);//单字节传输不涉及到大段小端传输转换。printf("MATH = %d\n",ntohl( rbuf.math));printf("CHINESE = %d\n",ntohl( rbuf.chinese));}close(sd);return 0;
}
snder.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>#include "proto.h"int main(int argc,char**argv)
{if(argc<2){printf("Usage argc 2...\n");exit(1);}int sd;sd = socket(AF_INET,SOCK_DGRAM,0);//     bind(); //可以省略int len;struct msg_st sbuf;struct sockaddr_in raddr;strcpy(sbuf.name,"udp test");sbuf.math = htonl( rand()%100);sbuf.chinese = htonl(rand()%100);raddr.sin_family = AF_INET;raddr.sin_port = htons(atoi(RECVPORT));inet_pton(AF_INET,argv[1],&raddr.sin_addr);len = sendto(sd,&sbuf,sizeof(sbuf),0,(void*)&raddr,sizeof(raddr) ); // tcp采用sendif(len <0){perror("sendto()");exit(1);}puts("Ok!");close(sd);return 0;
}

 变长实现

path:c/linux_c/ipc/socket/udp/var

proto.h
#ifndef PROTO_H
#define PROTO_H#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>#define IPSTRSIZE 128
#define NAMEMAX 512-8-8  //udp包推荐长度512 - 8 抱头 - 8(已有的math和chinese) #define RECVPORT "1989" //选择超过1024以上的端口struct msg_st
{
//    uint8_t  name[NAMESIZE]; //网络传输不能传递指针。uint32_t math;uint32_t  chinese;uint8_t name[1]; //变长结构体实现。/
}__attribute__((packed)); //告诉编译器结构体不用对齐#endif 
recv.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "proto.h"int main()
{int sd;sd  = socket(AF_INET,SOCK_DGRAM,0); //0代表默认的协议 IPPROTO_UDPif(sd <0){perror("socket");exit(1);}int ret;struct sockaddr_in laddr;laddr.sin_family = AF_INET;laddr.sin_port = htons(atoi(RECVPORT)); // 端口号 host to network 主机序列转为网络序列inet_pton(AF_INET,"0.0.0.0",&laddr.sin_addr);  //ip地址 需要转为大整数ret = bind(sd,(void *)&laddr,sizeof(laddr)); //不同的协议族绑定的地址是不一样的,需要man 7 ip 查看。if(ret<0 ){perror("bind()");exit(1);}struct msg_st* rbufp;int size = sizeof(struct msg_st)+NAMEMAX-1;rbufp = malloc(rbufp);struct sockaddr_in raddr;socklen_t raddr_len;char ipstr[IPSTRSIZE];/* raddr_len如果不初始化,那么第一次地址会出错,后续不会*/raddr_len = sizeof(raddr);while(1){recvfrom(sd,rbufp,size,0,(void *)&raddr,&raddr_len); //recv是流式套接字,recvform是报式,需要记录对端的地址。inet_ntop(AF_INET,&raddr.sin_addr,ipstr,IPSTRSIZE);printf("---MSSSAGE FORM %s:%d---\n",ipstr, ntohs(raddr.sin_port) ); //大整数转点分式printf("NAME = %s\n",rbufp->name);//单字节传输不涉及到大段小端传输转换。printf("MATH = %d\n",ntohl( rbufp->math));printf("CHINESE = %d\n",ntohl( rbufp->chinese));}close(sd);return 0;
}
sender.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>#include "proto.h"int main(int argc,char**argv)
{if(argc<3){printf("Usage argc 2...\n");exit(1);}if(strlen(argv[2])>NAMEMAX){fprintf(stderr,"Name is to Long");exit(1);}int sd;sd = socket(AF_INET,SOCK_DGRAM,0);//     bind(); //可以省略int len;struct msg_st* sbufp;int size = sizeof(struct msg_st)+strlen(argv[2]);sbufp =malloc(size);if(sbufp == NULL){perror("malloc()");exit(1);}struct sockaddr_in raddr;strcpy(sbufp->name,argv[2]);sbufp->math = htonl( rand()%100);sbufp->chinese = htonl(rand()%100);raddr.sin_family = AF_INET;raddr.sin_port = htons(atoi(RECVPORT));inet_pton(AF_INET,argv[1],&raddr.sin_addr);len = sendto(sd,sbufp,size,0,(void*)&raddr,sizeof(raddr) ); // tcp采用sendif(len <0){perror("sendto()");exit(1);}puts("Ok!");close(sd);return 0;
}

 多点通信

广播

path:c/linux_c/ipc/socket/udp/bcast  
man 7 socket 查看socket Options
ip ro sh:查看路由信息。
ip ro add default via 127.0.0.1:添加路由。

分为:全网广播、子网广播。默认不能够发出,需要特殊设置。

  int getsockopt(int sockfd, int level, int optname,
                      void *optval, socklen_t *optlen);
       int setsockopt(int sockfd, int level, int optname,
                      const void *optval, socklen_t optlen);

int val = 1;
setsockopt(sd,SOL_SOCKET,SO_BROADCAST,&val,sizeof(val));//每一层,每一个要求需要的参数都不一样。SO_BINDTODEVICE 可以指定从哪个网卡出去。
inet_pton(AF_INET,"255.255.255.255",&raddr.sin_addr); //ip地址 255是广播

多播

组播。

流式套接字

netstat -ant 查看流式套接字的信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/48348.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实现图片拖拽和缩小放大功能。

1. 前言 不知道各位前端小伙伴蓝湖使用的多不多&#xff0c;反正我是经常在用&#xff0c;ui将原型图设计好后上传至蓝湖&#xff0c;前端开发人员就可以开始静态页面的的编写了。对于页面细节看的不是很清楚可以使用滚轮缩放后再拖拽查看&#xff0c;还是很方便的。于是就花了…

RK3568 linux-5.10 rk809 声卡实现spk hp自动切换

文章目录 前言一、修改dts1、kernel/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi2、kernel/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi二、修改驱动1、kernel/sound/soc/codecs/rk817_codec.c2、kernel/sound/soc/rockchip/rockchip_multicodecs.c总结前言 l…

Springcloud之gateway的使用详解

官网地址&#xff1a;https://docs.spring.io/spring-cloud-gateway/docs/4.0.4/reference/html/ 1.网关入门 helloword 网关不依赖start-web 导入的pom&#xff1a; <!--gateway--> <dependency><groupIdorg.springframework.cloud</groupId><arti…

openEuler 知:版本比较

文章目录 前言工具oe_diffoepkg 前言 本文的“版本比较”主要是指比较 openEuler 操作系统两个版本之间的 rpm 包的版本差异&#xff0c;只比较版本差异&#xff0c;不比较文件内容的差异。 比较版本主要用于分析两个操作系统版本之间软件包的版本变化。 工具 oe_diff 工具…

Python面试整理-列表和元组的操作

在Python中,列表(list)和元组(tuple)是用于存储序列数据的两种主要数据类型。它们之间的主要区别在于,列表是可变的,而元组是不可变的。这意味着你可以修改列表中的元素,但不能修改元组中的元素。以下是一些常用的列表和元组的操作: 列表操作 创建列表 fruits = [&quo…

在 Ubuntu Server 22.04 上安装 Docker 的详细步骤

在 Ubuntu Server 22.04 上安装 Docker 的详细步骤 本文档详细记录了在 Ubuntu Server 22.04 上安装 Docker 的完整过程&#xff0c;包括解决过程中遇到的问题。希望能对读者有所帮助。 安装过程&#xff0c;重点需要看官方文档。https://docs.docker.com/engine/install/ubu…

C语言——字符串的输出、获取和复制总结

1.输出字符串 &#xff08;1&#xff09;puts char *p "aha c"; char str[128] {"hello world"};puts(p); puts(str); puts函数会自动在输出后进行换行。 &#xff08;2&#xff09;printf char *p "aha c"; char str[128] {"hell…

目标检测经典模型之YOLOV5-detect.py源码解析(持续更新)

detect文件框架 一、导入模块包二、定义run函数1. 归一化操作代码解析uint8精度转换归一化 2. 扩展维度为什么扩展维度&#xff1f;代码解释 3. 对检测结果类别计数检查是否有检测结果统计每个类别的出现次数构建描述性字符串 三、定义命令行参数四、主函数 本帖是YOLOV5推理部…

70. 爬楼梯【 力扣(LeetCode) 】

一、题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 二、测试用例 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1. 1 阶…

CUDA编程00 - 配置CUDA开发环境

第一步&#xff1a; 在一台装有Nvidia显卡和驱动的机器上&#xff0c;用nvidia-smi命令查看显卡所支持cuda版本 第二步&#xff1a; 到Nvidia官网下载CUDA Toolkit并安装&#xff0c;CUDA Toolkit Archive | NVIDIA Developer 安装时按提示下一步即可&#xff0c;安装完成用 …

【端智能】端智能技术演进与实践

什么是端智能技术 端智能&#xff08;On-Device Machine Learning&#xff09;是指把机器/深度学习算法模型应用和部署到端设备上&#xff0c;这里“端设备”是相对于云服务而言的&#xff0c;可以是手机&#xff0c;也可以是物联网IoT设备。 Google对端智能的介绍&#xff1…

系统架构设计师教程(清华第二版) 第3章 信息系统基础知识-3.2 业务处理系统-解读

教材中,一会儿“业务处理系统”,一会儿“事务处理系统”,语法毛病一堆。真是清华的水平!!! 系统架构设计师教程 第3章 信息系统基础知识-3.2 业务处理系统 3.2.1 业务处理系统的概念3.2.2 业务处理系统的功能3.2.2.1 数据输入3.2.2.2 数据处理3.2.2.2.1 批处理 (Batch …

计算机体系结构||指令的调度和延迟分布(3)

实验3 指令的调度和延迟分布 3.1实验目的 &#xff08;1&#xff09;加深对指令调度技术的理解。 &#xff08;2&#xff09;加深对延迟分支技术的理解。 &#xff08;3&#xff09;熟练掌握用指令调度技术来解决流水线中的数据冲突的方法。 &#xff08;4&#xff09;进一…

使用AI给编程赋能

传送门&#xff1a;https://www.bilibili.com/video/BV1pf421B71v?p23&vd_source092ecb16e8482a7243d0f8f7718c31a2 1. AIGC AI&#xff08;Artificial Intelligence&#xff09;&#xff1a;人工智能&#xff0c;是计算机科学体系下的一个学科&#xff0c;是指通过计算机…

c# 开发AutoCAD扩展

在C#中开发AutoCAD扩展涉及使用AutoCAD的.NET API&#xff0c; 利用AutoCAD的功能并创建自定义命令、对话框、块、图层和其他图形元素。以下是一些关键步骤和概念&#xff0c;可以帮助你开始使用C#开发AutoCAD扩展&#xff1a; 准备开发环境 安装AutoCAD&#xff1a;确保你有一…

在 macOS 上使用 Jadx 进行 APK 反编译

在 macOS 上使用 Jadx 进行 APK 反编译 Jadx 是一个流行的开源工具&#xff0c;用于将 Android APK 文件反编译成 Java 源代码。本文将详细介绍如何在 macOS 上安装和使用 Jadx&#xff0c;包括之前讨论的内容和步骤。 1. 安装 Jadx 在 macOS 上&#xff0c;可以通过 Homebr…

lua 游戏架构 之 SceneLoad场景加载(一)

设计一个为BaseSceneLoad class&#xff0c;用于处理场景加载的相关操作 &#xff0c;主要作用是提供了一个通用的场景加载框架&#xff0c;使得子类可以按照统一的接口进行场景加载操作。子类需要实现这些方法&#xff0c;以便在加载场景时能够正确地处理场景加载的各个阶段。…

【Linux】线程互斥和同步

目录 线程互斥 相关概念 互斥量mutex 互斥量的接口 初始化互斥量 销毁互斥量 互斥量加锁/解锁 可重入VS线程安全 概念 可重入与线程安全的联系 可重入与线程安全的区别 死锁 死锁的四个必要条件 避免死锁 避免死锁的算法 线程同步 条件变量 条件变量函数 初始…

语义分割——为什么单通道8bit灰度图像能显示多种色块???

目录 一、问题二、解答2.1 标签图的实际存储格式2.2 标签图的显示颜色2.3 颜色映射示例 三、应用颜色映射3.1 OpenCV显示标签图3.2 Matplotlib显示标签图 四、总结 一、问题 大家在做语义分割时不知道有没有这样的疑惑&#xff0c;使用打标签工具后&#xff0c;标签图是单通道…

项目收获总结--大数据量存储架构设计方案

项目收获总结--大数据量存储架构设计方案 一、背景二、数据存储层技术选型2.1 MySQL2.2 MongoDB2.3 HBase2.4 HBaseElasticSearch 三、HBaseElasticSearch基本原理3.1 前置考虑3.2 HBaseElasticSearch优点3.3 HBaseElasticSearch缺点 四、HBaseElasticSearch数据一致性架构4.1 …