当前位置: 首页 > news >正文

网站建设文件夹名字做旅游海报哪个网站好免费的

网站建设文件夹名字,做旅游海报哪个网站好免费的,东莞seo项目优化方法,广州建设网站首页进程间通信1 管道匿名管道命名管道2 消息队列3 信号量POSIX信号量有名信号量无名信号量有名信号量和无名信号量的公共操作4 共享内存5 信号相关函数6 套接字针对 TCP 协议通信的 socket 编程模型针对 UDP 协议通信的 socket 编程模型针对本地进程间通信的 socket 编程模型总结L… 进程间通信1 管道匿名管道命名管道2 消息队列3 信号量POSIX信号量有名信号量无名信号量有名信号量和无名信号量的公共操作4 共享内存5 信号相关函数6 套接字针对 TCP 协议通信的 socket 编程模型针对 UDP 协议通信的 socket 编程模型针对本地进程间通信的 socket 编程模型总结Linux下的进程通信机制叫做IPCInterProcess Communication在Linux下有6大通信的方法分别是Socket、管道、信号、信号量、消息队列、共享内存。 每个进程的用户地址空间都是独立的一般而言是不能互相访问的但内核空间是每个进程都共享的所以进程之间要通信必须通过内核。 1 管道 参考文章 https://blog.csdn.net/modi000/article/details/122084165https://blog.csdn.net/wm12345645/article/details/82381407 匿名管道 匿名管道是在内核中申请一块固定大小的缓冲区程序拥有写入和读取的权利。匿名管道是半双工的数据传输只能在一个方向并且只能在具有公共祖先的两个进程之间使用。 管道是通过调用pipe函数创建的 int pipe(int fd[2]);fd[0]为读端fd[1]为写端。 我们要注意调用 pipe之后管道是在内存中fd[0]和fd[1]还在进程当中现在只有调用pipe的进程才能对管道进行操作。那么怎么样才能使得管道是跨过两个进程使用呢 我们可使用fork创建子进程创建的子进程会继承来自父进程的文件描述符这样我们就做到两个进程各有1个fd[0]和fd[1]父子进程就可以往管道写入或读取数据实现通信了。 管道只能一端写入另一端读出所以上面这种模式容易造成混乱因为父进程和子进程都可以同时写入也都可以读出。那么为了避免这种情况通常的做法是 父进程关闭读取的 fd[0]只保留写入的 fd[1]子进程关闭写入的 fd[1]只保留读取的 fd[0] f[0]和f[1]都是文件描述符我们可以调用close函数关闭。比如关闭f[0] close(fd[0]);命名管道 命名管道是在内核申请一块固定大小的缓冲区程序拥有写入和读取的权利没有血缘关系的进程也可进行通信。由mkfifo函数创建 int mkfifo(const char *pathname,mode_t mode);创建一个名字由pathname指定的特殊文件在进程里只要使用这个文件就可以相互通信。 不管是匿名管道还是命名管道进程写入的数据都是缓存在内核中另一个进程读取数据时候自然也是从内核中获取同时通信数据都遵循先进先出原则不支持 lseek 之类的文件定位操作。 我们以pipe为例 #include stdio.h #include unistd.h #include stdlib.h #include fcntl.h #include sys/types.h#define BUFF_SIZE 1024int main(void){int fd[2];pid_t pid;char *str hello world;char buff[BUFF_SIZE];if(pipe(fd)!0){perror(pipe);exit(1);}pid fork();if(pid0){perror(fork());}else if(pid0){close(fd[0]);write(fd[1],str,sizeof(str));sleep(1);puts(write finished);}else{close(fd[1]);read(fd[0],buff,BUFF_SIZE);puts(read finished\n);printf(read source:%s\n,buff);}exit(0);}运行结果 2 消息队列 参考文章 https://zhuanlan.zhihu.com/p/268389190https://blog.csdn.net/modi000/article/details/122084165https://blog.csdn.net/ljianhui/article/details/10287879 消息队列是消息的链接表存储在内核中由消息队列标识符标识。 消息队列是保存在内核中的消息链表在发送数据时会分成一个一个独立的数据单元也就是消息体数据块消息体是用户自定义的数据类型消息的发送方和接收方要约定好消息体的数据类型所以每个消息体都是固定大小的存储块不像管道是无格式的字节流数据。如果进程从消息队列中读取了消息体内核就会把这个消息体删除。 创建一个消息队列是msgget函数实现的 int msgget(key_t key, int msgflg);它返回一个以key命名的消息队列标识符非零整数失败时返回-1. 可以用ftok创建一个key_t的值 key_t ftok(const char *pathname, int proj_id);功能通过ftok返回的是根据文件pathname信息和计划编号proj_id合成的IPC key键值。 返回值成功返回key_t值即IPC键值失败-1错误原因在error中 smgsnd函数添加消息到消息队列 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);msgid是由msgget函数返回的消息队列标识符msgp 参数是指向调用者定义的结构的指针其一般形式如下 struct msgbuf {long mtype; /* message type, must be 0 */char mtext[1]; /* message data */}; mtext是要发送的数据其类型是一个数组也可以是其他数据结构大小由msgsz指定msgsz必须是一个非负整数mtype 字段必须是正整数值接收函数可以使用该值进行消息选择msgflg用于控制当前消息队列满或队列消息到达系统范围的限制时将要发生的事情 msgrcv接受消息 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);msgtyp可以实现一种简单的接收优先级。如果msgtype为0就获取队列中的第一个消息。如果它的值大于零将获取具有相同消息类型和msgsnd函数msgbuf结构体的mtype相等的第一个信息。如果它小于零就获取类型等于或小于msgtype的绝对值的第一个消息。其他参数和msgsnd一样。 消息队列的控制函数msgctl int msgctl(int msqid, int cmd, struct msqid_ds *buf);command是将要采取的动作它可以取3个值 buf是指向msgid_ds结构的指针它指向消息队列模式和访问权限的结构。 发送进程msgsend.c #include stdio.h #include string.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/ipc.h #include sys/msg.h #include ./msgbuf.hint main(void) {int running 1;struct msgbuf data;long mtype0;key_t key; int msgid;/* 创建消息队列 */key ftok(./,2);if(key-1){printf(ftok error\n);exit(1);}/* 建立消息队列 */msgidmsgget(key,IPC_CREAT|0666);if(msgid-1){fprintf(stderr,msgget error);exit(1);}/* 发送数据 */while(running){printf(enter some test:);fgets(data.mtext,BUFFSIZE ,stdin);data.mtype 1;if(msgsnd(msgid,(void *)data,BUFFSIZE,0)-1){fprintf(stderr,msgsnd error\n);exit(1);}if(strncmp(data.mtext,end,3)0){running 0;}}exit(0); }接受进程代码msgrec.c #include stdio.h #include string.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/ipc.h #include sys/msg.h #include ./msgbuf.hint main(void) {int msgid;key_t key;int running 1;struct msgbuf data;memset(data.mtext,0,BUFFSIZE);long mtype0;key ftok(./,2);if(key-1){printf(ftok error\n);exit(1);}/* 建立消息队列 */msgidmsgget(key,IPC_CREAT|0666);if(msgid-1){fprintf(stderr,msgget error);exit(1);}/* 从队列中获取消息直到遇到end消息为止 */while(running){if(msgrcv(msgid,(void *)data,BUFFSIZE,mtype,0)-1){fprintf(stderr,msgrcv error with errno%d\n,errno);exit(1);}printf(message:%s\n,data.mtext);/* 删除消息队列 */if(strncmp(data.mtext,end,3)0){if(msgctl(msgid,IPC_RMID,NULL)0){printf(delete message queue success!\n);}running 0;}}exit(0); }msgbuf.h代码 #include errno.h#define BUFFSIZE 1024struct msgbuf{long mtype;char mtext[BUFFSIZE]; }; 运行结果 3 信号量 参考文章 https://blog.csdn.net/modi000/article/details/122084165https://zhuanlan.zhihu.com/p/351692436https://zhuanlan.zhihu.com/p/22612079 信号量与管道、消息队列不同它是一个计数器用于对多个进程提供对共享数据对象的访问也就是对临界资源进行保护。 信号量表示资源的数量为了获得共享资源进程需要执行下列操作 测试控制该资源的信号量若此信号量的值为正则进程可以使用该资源当使用该共享资源时进程会将信号量值减1表示它使用了一个资源单位。否则若此信号量的值为0则进程进入休眠状态直到信号量值大于0. 根据初始值的不同信号量可以细分为 2 类分别为二进制信号量和计数信号量 二进制信号量指初始值为 1 的信号量此类信号量只有 1 和 0 两个值通常用来替代互斥锁实现进程同步 计数信号量指初始值大于 1 的信号量当进程中存在多个进程但某公共资源允许同时访问的进程数量是有限的出现了“狼多肉少”的情况这时就可以用计数信号量来限制同时访问资源的进程数量。 POSIX信号量 POSIX信号量是一个sem_t类型的变量但POSIX有两种信号量的实现机制无名信号量和命名信号量。 无名信号量只可以在共享内存的情况下使用比如实现进程中各个线程之间的互斥和同步因此无名信号量也被称作基于内存的信号量命名信号量通常用于不共享内存的情况下比如进程间通信。 有名信号量 有名信号量由于其有名字 多个独立的进程可以通过名字来打开同一个信号量 从而完成同步操作 所以有名信号量的操作要方便一些 适用范围也比无名信号量更广。 创建有名信号量 sem_t *sem_open(const char *name, int oflag); sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value);2. 有名信号量的关闭 int sem_close(sem_t *sem);当一个进程打开有名信号量时 系统会记录进程与信号的关联关系。 调用sem_close时 会终止这种关联关系 同时信号量的进程数的引用计数减1。 有名信号量的删除 int sem_unlink(const char *name);函数会负责将该有名信号量删除。 由于系统为信号量维护了引用计数 所以只有当打开信号量的所有进程都关闭了之后 才会真正地删除。 无名信号量 无名信号量 由于其没有名字 所以适用范围要小于有名信号量。 只有将无名信号量放在多个进程或线程都共同可见的内存区域时才有意义 否则协作的进程无法操作信号量 达不到同步或互斥的目的。 所以一般而言 无名信号量多用于线程之间。 因为线程会共享地址空间 所以访问共同的无名信号量是很容易办到的事情。 或者将信号量创建在共享内存内 多个进程通过操作共享内存的信号量达到同步或互斥的目的。 无名信号量的创建 int sem_init(sem_t *sem, int pshared, unsigned int value);无名信号量的生命周期是有限的 对于线程间共享的信号量 线程组退出了无名信号量也就不复存在了。 对于进程间共享的信号量 信号量的持久性与所在的共享内存的持久性一样。 无名信号量初始化以后 就可以像操作有名信号量一样操作无名信号量了。 无名信号量的销毁 int sem_destroy(sem_t *sem);sem_destroy用于销毁sem_init函数初始化的无名信号量。 只有在所有进程都不会再等待一个信号量时 它才能被安全销毁。 有名信号量和无名信号量的公共操作 获取信号量 #include semaphore.hint sem_wait(sem_t *sem);int sem_trywait(sem_t *sem);int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);Link with -pthread. 归还信号量2 int sem_post(sem_t *sem);获取当前信号量的值 int sem_getvalue(sem_t *restrict, int *restrict);我们用信号量解决生产者拿消费者问题 #include stdio.h #include pthread.h #include semaphore.h #include stdlib.h#define N 10 #define true 1void show_buffer(); void *producer(void *id); void *consumer(void *id);typedef int item; //环形队列 int in 0, out 0; //缓冲区 item buffer[N]; //互斥、空缓冲区、满缓冲区信号量 sem_t mutex,empty,full;/* 生产者 */ void *producer(void *id) {while(true){item nextp rand() % 10;sem_wait(empty);sem_wait(mutex);buffer[in]nextp;in (in)%N;printf(%s\n,(char *)id);printf(生产了:%d\n,nextp);show_buffer();sem_post(mutex);sem_post(full);} }/* 消费者 */ void *consumer(void *id) {while(true){sem_wait(full);sem_wait(mutex);item nextc buffer[out];out (out)%N;int emp,ful;sem_getvalue(empty,emp);sem_getvalue(full,ful);printf(%s\n缓冲区大小%d\n消费的物品%d\n空缓冲区的数量%d\n满缓冲区的数量%d\n,(char*)id,N,nextc,emp,ful);show_buffer();sem_post(mutex);sem_post(empty);} }/* 显示缓冲区内容 */ void show_buffer() {printf([ );if(inout)//满for(int i0;iN;i)printf(%2d ,buffer[i]);else if(outin)for(int iout ;(i%N)in;i)printf(2%d ,buffer[i]);else{for(int iout;iN;i)printf(%2d ,buffer[i]);for(int i0;iin;i)printf(%2d ,buffer[i]);}printf(]\n); }int main(void) {/*初始化信号量*/if(sem_init(mutex,0,1)-1)perror(sem_init);if(sem_init(empty,0,N)-1)perror(sem_init);if(sem_init(full,0,0)-1)perror(sem_init);/* 两个生产者、两个消费者 */pthread_t p1,p2,c1,c2;int ret;if((retpthread_create(p1,NULL,producer,(void *)生产者1))!0){fprintf(stderr,ptheard_create error,error number :%d\n,ret);exit(1);}if((retpthread_create(p2,NULL,producer,(void *)生产者2))!0){fprintf(stderr,ptheard_create error,error number :%d\n,ret);exit(1);}if((retpthread_create(c1,NULL,consumer,(void *)消费者1))!0){fprintf(stderr,ptheard_create error,error number :%d\n,ret);exit(1);}if((retpthread_create(c2,NULL,consumer,(void *)消费者2))!0){fprintf(stderr,ptheard_create error,error number :%d\n,ret);exit(1);}if(retpthread_join(p1,NULL)){fprintf(stderr,ptheard_join error,error number :%d\n,ret);exit(1);}if(retpthread_join(p2,NULL)){fprintf(stderr,ptheard_join error,error number :%d\n,ret);exit(1);}if(retpthread_join(c1,NULL)){fprintf(stderr,ptheard_join error,error number :%d\n,ret);exit(1);}if(retpthread_join(c2,NULL)){fprintf(stderr,ptheard_join error,error number :%d\n,ret);exit(1);}return 0;} 4 共享内存 参考文章 https://blog.csdn.net/modi000/article/details/122084165https://zhuanlan.zhihu.com/p/147826545 共享内存的机制就是进程拿出一块虚拟地址空间来映射到相同的物理内存中。这样这个进程写入的东西另外一个进程马上就能看到了都不需要拷贝来拷贝去大大提高了进程间通信的速度。 打开或创建共享内存 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);接下来我们做这么一个例子创建两个进程在 A 进程中创建一个共享内存并向其写入数据通过 B 进程从共享内存中读取数据。 写端 #include stdio.h #include stdlib.h #include sys/ipc.h #include sys/shm.h #include sys/types.h #include string.h#define SIZE 1024void printf_error(void *s) {fprintf(stderr,%s\n,(char *)s);exit(1); }int main(void) {key_t key;int shmid;int ret;/*创建key值 */key ftok(../,2021);if(key-1){printf_error(ftok error);}/* 创建共享内存 */shmid shmget(key,SIZE ,IPC_CREAT|0666);if(shmid-1){printf_error(shmget error);}/* 映射 */char *shmad shmat(shmid,NULL,0);if(shmad 0){printf_error(shmat error);}/* 拷贝数据至共享内存区 */memset(shmad,0,SIZE);strcpy(shmad,How are you,mike\n);return 0; } 读端 #include stdio.h #include stdlib.h #include string.h #include sys/types.h #include sys/ipc.h #include sys/shm.h#define SIZE 1024void printf_error(void *s) {fprintf(stderr,%s\n,(char *)s);exit(1); } int main(void) {int shmid;key_t key;int ret;/* 创建key值 */key ftok(../,2021);if(key-1){printf_error(ftok error);}system(ipcs -m); //查看共享内存//打开共享内存shmid shmget(key,SIZE,IPC_CREAT|0666);if(shmid0){printf(shmget error);}// 映射char *shmad shmat(shmid,NULL,0);if(shmad0){printf_error(shmat error);}// 读取共享内存区数据printf(data [%s]\n,shmad);//分离共享内存和当前进程ret shmdt(shmad);if(ret0){printf_error(shmdt error);}printf(deleted shared_memory\n);//删除共享内存shmctl(shmid,IPC_RMID,NULL);system(ipcs -m);return 0; }5 信号 参考文章 https://blog.csdn.net/modi000/article/details/122084165https://www.cnblogs.com/electronic/p/10939769.html 对于异常情况下的工作模式就需要用「信号」的方式来通知进程。 信号是进程间通信机制中唯一的异步通信机制因为可以在任何时候发送信号给某一进程一旦有信号产生我们就有下面这几种用户进程对信号的处理方式。 执行默认操作。Linux 对每种信号都规定了默认操作例如 SIGTERM 信号就是终止进程的意思。Core 的意思是 Core Dump也即终止进程后通过 Core Dump 将当前进程的运行状态保存在文件里面方便程序员事后进行分析问题在哪里。 捕捉信号。我们可以为信号定义一个信号处理函数。当信号发生时我们就执行相应的信号处理函数。 忽略信号。当我们不希望处理某些信号的时候就可以忽略该信号不做任何处理。有两个信号是应用进程无法捕捉和忽略的即 SIGKILL 和 SEGSTOP它们用于在任何时候中断或结束某一进程 相关函数 int kill(pid_t pid, int sig); 功能信号发送 参数pid指定进程 sig要发送的信号 返回值成功 0失败 -1int raise(int sig); 功能进程向自己发送信号 参数sig信号 返回值成功 0失败 -1unsigned int alarm(unsigned int seconds) 功能在进程中设置一个定时器 参数seconds定时时间单位为秒 返回值如果调用此alarm()前进程中已经设置了闹钟时间则返回上一个闹钟时间的剩余时间否则返回0。 注意一个进程只能有一个闹钟时间。如果在调用alarm时已设置过闹钟时间则之前的闹钟时间被新值所代替 int pause(void); 功能用于将调用进程挂起直到收到信号为止。 信号处理函数 typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);功能信号处理函数 参数 signum要处理的信号//不能是SIGKILL和SIGSTOP handler 1. SIG_IGN忽略该信号 2. SIG_DFL采用系统默认方式处理信号。 3. 自定义的信号处理函数指针 返回值成功设置之前的信号处理方式失败SIG_ERR void abort(void); 给自己发送异常终止信号SIGABRO终止并产生core文件。 #include stdio.h #include stdlib.h #include signal.h #include sys/types.h #include unistd.hvoid handler(int num) {printf( this signal no. is %d\n,num);kill(getpid(),SIGTERM); }int main(void) {signal(SIGINT,handler);while(1);return 0; }6 套接字 文章来源 https://blog.csdn.net/modi000/article/details/122084165 前面提到的管道、消息队列、共享内存、信号量和信号都是在同一台主机上进行进程间通信那要想跨网络与不同主机上的进程之间通信就需要 Socket 通信了。 创建一个socket int socket(int domain, int type, int protocal)三个参数分别代表 domain 参数用来指定协议族比如 AF_INET 用于 IPV4、AF_INET6 用于 IPV6、AF_LOCAL/AF_UNIX 用于本机type 参数用来指定通信特性比如 SOCK_STREAM 表示的是字节流对应 TCP、SOCK_DGRAM 表示的是数据报对应 UDP、SOCK_RAW 表示的是原始套接字protocal 参数原本是用来指定通信协议的但现在基本废弃。因为协议已经通过前面两个参数指定完成protocol 目前一般写成 0 即可 根据创建 socket 类型的不同通信的方式也就不同 实现 TCP 字节流通信 socket 类型是 AF_INET 和 SOCK_STREAM实现 UDP 数据报通信socket 类型是 AF_INET 和 SOCK_DGRAM实现本地进程间通信 「本地字节流 socket 」类型是 AF_LOCAL 和 SOCK_STREAM「本地数据报 socket 」类型是 AF_LOCAL 和 SOCK_DGRAM。另外AF_UNIX 和 AF_LOCAL 是等价的所以 AF_UNIX 也属于本地 socket 针对 TCP 协议通信的 socket 编程模型 服务端和客户端初始化 socket得到文件描述符服务端调用 bind将绑定在 IP 地址和端口;服务端调用 listen进行监听服务端调用 accept等待客户端连接客户端调用 connect向服务器端的地址和端口发起连接请求服务端 accept 返回用于传输的 socket 的文件描述符客户端调用 write 写入数据服务端调用 read 读取数据客户端断开连接时会调用 close那么服务端 read 读取数据的时候就会读取到了 EOF待处理完数据后服务端调用 close表示连接关闭。 这里需要注意的是服务端调用 accept 时连接成功了会返回一个已完成连接的 socket后续用来传输数据。 所以监听的 socket 和真正用来传送数据的 socket是「两个」 socket一个叫作监听 socket一个叫作已完成连接 socket。 成功连接建立之后双方开始通过 read 和 write 函数来读写数据就像往一个文件流里面写东西一样。 针对 UDP 协议通信的 socket 编程模型 UDP 是没有连接的所以不需要三次握手也就不需要像 TCP 调用 listen 和 connect但是 UDP 的交互仍然需要 IP 地址和端口号因此也需要 bind。 对于 UDP 来说不需要要维护连接那么也就没有所谓的发送方和接收方甚至都不存在客户端和服务端的概念只要有一个 socket 多台机器就可以任意通信因此每一个 UDP 的 socket 都需要 bind。 另外每次通信时调用 sendto 和 recvfrom都要传入目标主机的 IP 地址和端口。 针对本地进程间通信的 socket 编程模型 本地 socket 被用于在同一台主机上进程间通信的场景 本地 socket 的编程接口和 IPv4 、IPv6 套接字编程接口是一致的可以支持「字节流」和「数据报」两种协议本地 socket 的实现效率大大高于 IPv4 和 IPv6 的字节流、数据报 socket 实现 对于本地字节流 socket其 socket 类型是 AF_LOCAL 和 SOCK_STREAM。 对于本地数据报 socket其 socket 类型是 AF_LOCAL 和 SOCK_DGRAM。 本地字节流 socket 和 本地数据报 socket 在 bind 的时候不像 TCP 和 UDP 要绑定 IP 地址和端口而是绑定一个本地文件这也就是它们之间的最大区别。 总结 Linux 内核提供了不少进程间通信的方式其中最简单的方式就是管道管道分为「匿名管道」和「命名管道」。 匿名管道顾名思义它没有名字标识匿名管道是特殊文件只存在于内存没有存在于文件系统中shell 命令中的「|」竖线就是匿名管道通信的数据是无格式的流并且大小受限通信的方式是单向的数据只能在一个方向上流动如果要双向通信需要创建两个管道再来匿名管道是只能用于存在父子关系的进程间通信匿名管道的生命周期随着进程创建而建立随着进程终止而消失。 命名管道突破了匿名管道只能在亲缘关系进程间的通信限制因为使用命名管道的前提需要在文件系统创建一个类型为 p 的设备文件那么毫无关系的进程就可以通过这个设备文件进行通信。另外不管是匿名管道还是命名管道进程写入的数据都是缓存在内核中另一个进程读取数据时候自然也是从内核中获取同时通信数据都遵循先进先出原则不支持 lseek 之类的文件定位操作。 消息队列克服了管道通信的数据是无格式的字节流的问题消息队列实际上是保存在内核的「消息链表」消息队列的消息体是可以用户自定义的数据类型发送数据时会被分成一个一个独立的消息体当然接收数据时也要与发送方发送的消息体的数据类型保持一致这样才能保证读取的数据是正确的。消息队列通信的速度不是最及时的毕竟每次数据的写入和读取都需要经过用户态与内核态之间的拷贝过程。 共享内存可以解决消息队列通信中用户态与内核态之间数据拷贝过程带来的开销它直接分配一个共享空间每个进程都可以直接访问就像访问进程自己的空间一样快捷方便不需要陷入内核态或者系统调用大大提高了通信的速度享有最快的进程间通信方式之名。但是便捷高效的共享内存通信带来新的问题多进程竞争同个共享资源会造成数据的错乱。 那么就需要信号量来保护共享资源以确保任何时刻只能有一个进程访问共享资源这种方式就是互斥访问。信号量不仅可以实现访问的互斥性还可以实现进程间的同步信号量其实是一个计数器表示的是资源个数其值可以通过两个原子操作来控制分别是 P 操作和 V 操作。 与信号量名字很相似的叫信号它俩名字虽然相似但功能一点儿都不一样。信号是进程间通信机制中唯一的异步通信机制信号可以在应用进程和内核之间直接交互内核也可以利用信号来通知用户空间的进程发生了哪些系统事件信号事件的来源主要有硬件来源如键盘 CltrC 和软件来源如 kill 命令一旦有信号发生进程有三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号。有两个信号是应用进程无法捕捉和忽略的即 SIGKILL 和 SEGSTOP这是为了方便我们能在任何时候结束或停止某个进程。 前面说到的通信机制都是工作于同一台主机如果要与不同主机的进程间通信那么就需要 Socket 通信了。Socket 实际上不仅用于不同的主机进程间通信还可以用于本地主机进程间通信可根据创建 Socket 的类型不同分为三种常见的通信方式一个是基于 TCP 协议的通信方式一个是基于 UDP 协议的通信方式一个是本地进程间通信方式。
http://www.zqtcl.cn/news/757789/

相关文章:

  • 红叶网站开发工作室整站优化费用
  • 温州网站建站模板建设小企业网站步骤
  • 免费企业网站我为什么电商要学网站建设
  • 建设网站员工招聘策划方案win2012 iis配置网站
  • 织梦cms 5.6网站地图图标怎么在wordpress
  • instagram wordpress北京seo学校
  • 网站优化的基本思想企业网站建设和运营
  • 网站开发电销常遇到问题怎么建立一个群
  • worldpress 建站少儿编程加盟费一般多少钱
  • 哪个公司做网站建设好九一人才网赣州招聘官网
  • 城阳区规划建设局网站哈尔滨网站建设好
  • 中小型网站建设价位无锡有哪些互联网公司
  • 网站内容收费jquery 网站框架
  • 自己建网站买玩具外贸网站如何做推广
  • 网站 配色表注册公司有什么风险
  • 网站管理员登陆后缀重庆建筑证书查询网站
  • 义乌seoseo建站外贸
  • 只做早餐的网站老网站做seo能不能重新注册
  • 门户网站开发需要多少钱百姓网网站源码
  • 网站设计要学哪些保山网站建设
  • 怎样免费设计网站建设企业网站系统源码
  • 海报设计模板网站找网络公司做网站需要注意
  • 网站开发前端后端书籍wordpress 加文章列表
  • 泰安北京网站建设商业网站的后缀一般为
  • 必须网站的访问量wordpress标题大小
  • qq怎么做放资源的网站英语seo什么意思
  • 学生心理健康网站建设论文php开源内容管理系统
  • 机关网站内容建设雄安专业网站建设
  • 有域名有空间怎么做网站怎么制作网站封面
  • 注册域名哪个网站好信息技术制作网站首页