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

网络营销导向企业网站建设的一般原则是什么?河北省保定市唐县城乡建设网站

网络营销导向企业网站建设的一般原则是什么?,河北省保定市唐县城乡建设网站,网络营销推广的要点,广告设计作品文章目录进程间通信进程通信的意义进程通信的方式1.基于文件的方式匿名管道命名管道2.基于内存的通信方式共享内存验证内核相关的数据结构了解进程间通信 进程通信的意义 ​ 当我们和另一个人打电话时两部手机都是独立的#xff0c;通过基站传递信号等等复杂的过程就实现了通… 文章目录进程间通信进程通信的意义进程通信的方式1.基于文件的方式匿名管道命名管道2.基于内存的通信方式共享内存验证内核相关的数据结构了解进程间通信 进程通信的意义 ​ 当我们和另一个人打电话时两部手机都是独立的通过基站传递信号等等复杂的过程就实现了通信。那么进程间是如何进行通信的呢 ​ 我们知道进程是具有独立性的即使是fork创建的子进程也一样那么有时我们需要让两个进程进行协同工作例如一个进程发送信号另一个进程接收信号执行对应的操作再或者子进程把自己的数据交付给父进程让其处理拦截一些异常信号等等。 ​ 由于进程是独立的是互相看不到对方的数据的所以想要进行通信就必须看到一份公共资源这里的公共资源是操作系统提供的一段内存是属于操作系统的。这段内存由于提供的方式不一样会使通信的方式多样性例如文件struct file方式、队列、数组、原始内存块等等所以进程间通信是具有一定的成本的。 进程通信的方式 1.基于文件的方式 ​ 先来梳理一下当一个进程打开文件时的进程内核角度是怎么样的 ​ 那么fork之后的子进程是什么样的呢 ​ 也就是拷贝了父进程的代码和数据以父进程为模板初始化浅拷贝所以子进程和父进程就指向了同一个文件此时这个文件就是公共资源。 ​ 那么我们可以让父子进程在指向同一个文件的前提下一个负责读缓冲区一个负责往缓冲区写但不调用底层的读写函数不往文件上刷新就实现了进程间的通信这种基于文件的通信方式就叫做管道 站在操作系统角度下一切皆文件 所以管道是一个单向通信的通信通道半双工 匿名管道 ​ 进程是具有独立性的想让进程间通信其实成本是比较高的因为必须解决一个问题创建出一份公共资源内存、队列、文件、缓冲区让不同的进程看到因此操作系统提供了一个函数接口 int pipe(int pipefd[2])可以创建一个匿名管道 管道没有名字只能在具有公共祖先的进程(父进程和子进程或两个兄弟进程)之间使用所以叫做匿名管道 头文件 #include unistd.h参数pipefd[2]是一个输出型参数通过这个参数读取到打开的两个fd返回值若成功返回0若出错返回-1并设置errno ​ 匿名管道实际上是一种固定大小的缓冲区匿名管道对于管道两端的进程而言就是一个文件可以看成它是一种特殊的文件并且只存在于内存中。 如何利用pipe实现通信 父进程利用pipe获取到两个文件描述符父进程fork出子进程子进程以父进程为模板初始化得到一份相同的struct file* array[ ]一个负责读一个负责写但要不能冲突且要关闭不用的文件描述符接口 示例1 写端写的慢或者不写读端要等写端 管道带有同步机制读走的数据和写入数据是在管道内部是同步的且数据一旦被读走它就从管道中丢弃 写端退出读端读完pipe内部数据后也退出 ​ 示例2 读端读的慢或读端不读写端要等读端 现象1为什么一行读取很多个 hello 你好 ​ 只要匿名管道里还有空间写的一端就会一直按字节为单位地写只要管道内还有数据读的一端就会一直按字节为单位地读直到返回0表明读到文件末尾是面向字节流的 字节流按字节写入按字节读取 也就是子进程不断在写而父进程延时读取读的时候管道有多少字节读都多少字节所以可以看到读取很多 现象2为什么读到65536就不读了 实际是因为管道内的大小为64KB65536/1024 64 所以写端在等读端读取write置阻塞等待读取一定的大的字节后才会继续写入 即 当要写入的数据量不大于PIPE_BUF时linux将保证写入的原子性。当要写入的数据量大于PIPE_BUF时linux将不再保证写入的原子性。 写端写满后读端至少读取4KB数据才能唤醒写端使写端继续写同时写说明管道自带同步机制不会出现新老数据覆盖的问题。 ​ 读端关闭写端也退出产生终止信号并导致子进程退出只有在管道的读端存在时向管道中写入数据才有意义 ​ 否则向管道中写入数据的进程将收到内核传来的SIFPIPE信号应用程序可以处理该信号也可以忽略默认动作则是应用程序终止 匿名管道读写规则 读端不读或者读端读的慢写端要等读端管道的大小是64kb管道写满时最少读走4KB才会继续写入write挂起等待暂停写入写端不写或者写端写的慢读端要等写端没有数据时read挂起等待暂停读取读端关闭写端产生终止信号13SIGPIPE直接终止写端关闭读端读完内部数据后关闭read返回0代表读到末尾了 管道的特点 管道是一个单向通信的通道半双工 管道是面向字节流的具体体现在写端等读端读端读的时候读取所有写入的字节按字节写入按字节读取所以一般双方会规定一些协议 管道自带同步机制原子性写入读过的数据和写入的数据在管道内部是同步的所以不会出现读到老数据或新数据覆盖问题 匿名管道是在带有继承关系的进程下完成的 管道的生命周期是随着进程的 ​ 管道也是文件只要被一个进程打开struct file的引用计数就会1相关进程退出引用计数就-1引用计数为0时OS会自动关闭管道文件 命名管道 ​ 匿名管道只能用于具有继承关系的进程间通信这就导致有很大局限性无法在两个不相干的进程间通信。 ​ 假如在目录中创建一个真实存在的文件就可以让不同的进程打开同一份文件了那么操作系统提供了mkfifo函数可创建一个命名管道文件 int mkfifo(const char *pathname, mode_t mode); // 返回值成功返回0出错返回-1头文件#include sys/stat.hpathname文件名路径mode参数与open函数中的 mode 相同表示创建这个文件的权限 int main() { umask(0); if(mkfifo(./myfifo,0666) 0) { perror(mkfifo:); return 1; } return 0; } 命名管道文件有路径名与之相关联它以一种特殊设备文件形式存在于文件系统中 命名管道文件不会重复创建 命名管道具有匿名管道所有特点创建好管道文件后只需要像文件操作一样即可实现不同进程间通信 /*************************************out.c*************************************/#include stdio.h #include stdlib.h #include string.h #include unistd.h #include sys/stat.h #include sys/types.h #include fcntl.h #include sys/wait.h int main() {//创建管道文件umask(0);if(mkfifo(./myfifo,0666) 0){perror(mkfifo:);return 1;}//打开文件int fd open(./myfifo,O_RDONLY);if(fd 0){perror(open:);return 1;}while(1){char buffer[64] {0};ssize_t ret read(fd,buffer,sizeof(buffer)-1 ); //期望读取63个但读到末尾就停止留出一个位置 置一个\0虽然内核存储没有\0但是使用printf打印是C的接口需要置一个\0buffer[ret] 0; //置\0 if(ret 0){if(strcmp(buffer,show) 0) {if(fork() 0) //利用子进程替父进程执行命令{execl(/usr/bin/ls,ls,-a,-l,NULL); //进程替换exit(-1); }int status 0;waitpid(-1,status,0); //进程等待if(WIFEXITED(status)) //获取进程正常执行退出的退出码printf(exit code:%d\n,WEXITSTATUS(status));else if(WIFSIGNALED(status)) //获取进程退出异常的信号printf(exit signal:%d\n,WTERMSIG(status)); }printf(%s\n,buffer);}else if(ret 0){printf(out quit...\n);break;}else {perror(read:);break; }}close(fd);return 0; } /*************************************put.c*************************************/ #include stdio.h #include stdlib.h #include string.h #include unistd.h #include sys/stat.h #include sys/types.h #include fcntl.hint main() {//有一个创建管道文件即可管道文件不可重复创建/* umask(0);if(mkfifo(./myfifo,0666) 0){perror(mkfifo:);return 1;} *///推荐系统调用接口可以减少一些拷贝如C提供的用户缓冲区int fd open(./myfifo,O_WRONLY); //只写if(fd 0){perror(open:);return 1;}//发布命令while(1){char buffer[64] {0}; //先把要发布的命令保存printf(请输入);fflush(stdout);ssize_t ret read(0,buffer,sizeof(buffer)-1); //\0只是C语言规定的read是系统调用接口是没有\0这个概念的if(ret 0){buffer[ret - 1] 0; //因为输入完要按回车所以要去除\nwrite(fd,buffer,ret); //发布命令}}close(fd);return 0; } 现在让out不读而put一直写 管道文件不会真的刷新到磁盘只会在缓冲区中进行读写可以节省效率 管道总结 ​ 管道是最基本的进程间通讯它是单向通讯类似半双工。它属于内存缓冲区中申请的一份公共资源是一种特殊的文件用于连接一个写进程一个读进程。一个进程把数据写入管道由内核定向的流入另一个读进程。 命名管道为了保证不同的进程看到同一个文件必须有名字 匿名管道文件没有名字因为他是通过进程继承方式看到同一份资源的不需要名字标识 读写规则 读端不读或者读端读的慢写端要等读端管道的大小是64kb管道写满时最少读走4KB才会继续写入write挂起等待暂停写入写端不写或者写端写的慢读端要等写端没有数据时read挂起等待暂停读取读端关闭写端产生终止信号13SIGPIPE直接终止写端关闭读端读完内部数据后关闭read返回0代表读到末尾了 管道的特点 管道是一个单向通信的通道半双工 管道是面向字节流的具体体现在写端等读端读端读的时候读取所有写入的字节按字节写入按字节读取所以一般双方会规定一些协议 管道自带同步机制原子性写入读过的数据和写入的数据在管道内部是同步的所以不会出现读到老数据或新数据覆盖问题 匿名管道是在带有继承关系的进程下完成的 管道的生命周期是随着进程的 ​ 管道也是文件只要是文件被一个进程打开struct file的引用计数就会1相关进程退出引用计数就-1引用计数为0时OS会自动关闭管道文件 2.基于内存的通信方式 共享内存 ​ 进程间通信的本质是先让不同的进程看到同一份资源除了前面介绍的管道通信还有一些其他的方式systemV标准是在操作系统层面专门为同一主机内的进程间通信设计的一个方案。 systemV常见的通信方式有以下3种 共享内存本篇介绍消息队列信号量 ​ ​ 共享内存就是让多个进程地址空间在同一个物理内存通过映射的方式在页表中建立的联系 那么我们可以通过某种方式在内存中申请一块空间让进程都“挂接“上这块内存等于让不同的进程看到了同一份资源 ​ 那么上述介绍的就是共享内存的原理 那么如何实现申请和挂接呢若是不用了以后呢所以可分为以下4个步骤 申请内存挂接到内存去除挂接释放内存 这4个步骤都是利用OS提供的接口函数 申请内存需要用到系统提供的 int shmget(key_t key, size_t size, int shmflg); 函数接口 key key表示共享内存的键值可以自己填写也可以由一个算法生成key_t ftok(const char *pathname, int proj_id); 生成成功则会返回 路径id转换的IPC键值 生成失败返回 -1 size size表示想申请的空间大小os是按4kb为基准值分配的不满4kb的会向上调整分配为4kb所以这里建议按4kb的倍数申请 shmflg shmflg可以设置申请方式以及权限这里介绍两种 IPC_CREAT单独使用或者不用即shmflg0时表示申请的内存时的key值若存在则返回这个内存的shmid号返回值若不存在则申请到共享内存 ​ IPC_EXCLIPC_EXCL单独使用没有任何意义要配合IPC_CREAT使用IPC_EXCL|IPC_CREAT表示若申请内存的key已经存在则返回错误-1若不存在则创建 最后在后面或上8进制形式的权限即可 返回值 申请成功返回一个id号shmid类似文件描述符fd也是一个数组的下标。 具体这个数组关连的哪些数据结构在后面介绍 申请失败返回-1 ​ shmget使用类似于管道一个申请另一个只要保证申请时传入的key是相同就可以获取到申请内存返回的shmid而ftok函数保证传入的自定义路径和自定义id是相同的就可以获取到相同的key值 ​ 而通过运行结果可以反映出程序结束并不会回收这个内存所以out再次运行时会申请失败put再次运行还是可以获取到 在命令行输入 ipcs -m 可以查看共享内存使用情况 注意system V的IPC资源生命周期是随内核的只能通过显示释放命令、system call或者重启OS 命令行输入 ipcrm -m shmid号 可释放内存 释放内存需要用到的 int shmctl(int shmid, int cmd, struct shmid_ds *buf); 函数接口 上面介绍了命令行的释放实际应该像申请动态内存、打开文件那样要在程序中中做到谁申请谁释放 所以可以用 shmctl控制内存函数 成功返回0 失败返回-1 这里只介绍删除在cmd参数传入 IPC_RMID若cmd传的是IPC_RMID第三个参数传NULL即可 进程挂载内存需要用到 void *shmat(int shmid, const void *shmaddr, int shmflg);接口函数 挂接内存的本质是让进程地址空间与共享内存在页表建立映射关系 shmid就是申请内存时返回的的shmid共享内存标识符 shmaddr指定挂接的地址一般填NULL即可真实情况只有OS清楚 shmflg表示挂接方式一般设置0 返回值 挂接成功返回首地址也就是进程地址空间中对应页表映射的首地址类似于malloc失败返回-1 取消挂载用到int shmdt(const void *shmaddr);函数接口 取消挂接的本质是取消进程地址空与共享内存在页表的映射关系 shmaddr挂载时返回给用户的地址 返回值 成功返回0失败返回-1 验证 /************************************com.h***************************************/ #pragma once #include stdio.h #include stdlib.h #include unistd.h #include string.h #include sys/types.h #include fcntl.h #include sys/wait.h #include sys/ipc.h #include sys/shm.h/************************************out.c***************************************/ #include com.hint main() {key_t key ftok(.,0x666);if(key 0){perror(ftok:);return 1;}//申请共享内存int shmid shmget(key,4097,IPC_CREAT|IPC_EXCL|0666);if(shmid 0){perror(shmget);return 1;}printf(key:%#x shmid:%d\n,key,shmid);printf(申请成功\n);sleep(10);//挂接页表-虚拟内存挂接成功返回起始地址挂接到页表后返回映射的虚拟地址中的首地址char* addr (char*)shmat(shmid,NULL,0);if(addr NULL){perror(shmat);return 1;}sleep(10);printf(挂接成功\n);//通信#############while(1){sleep(1);printf(%s\n,addr);}//##################//取消挂接,本质是去除进程地址空间与共享内存在页表的映射关系shmdt(addr);sleep(10);printf(取消挂接\n);//释放共享内存shmctl(shmid,IPC_RMID,NULL);printf(释放内存\n);return 0; }/************************************put.c***************************************/#include com.hint main() {key_t key ftok(.,0x666);if(key 0){perror(ftok:);return 1;}//申请共享内存int shmid shmget(key,4097,IPC_CREAT);//获取if(shmid 0){perror(shmget);return 1;}printf(key:%#x shmid:%d\n,key,shmid);printf(获取成功\n);sleep(10);//挂接页表-虚拟内存挂接成功返回起始地址挂接到页表后返回映射的虚拟地址中的首地址char* addr (char*)shmat(shmid,NULL,0);if(addr NULL){perror(shmat);return 1;}sleep(5);printf(挂接成功\n);//通信############while(1){char ch A;while(ch Z){addr[ch - A] ch; //[0] Ach; //CH Baddr[ch - A] 0; //[1] Bsleep(1);}}//#################//取消挂接shmdt(addr);sleep(10);printf(取消挂接\n);//释放内存//谁申请谁释放这里的内存是out.c申请的/*shmctl(shmid,IPC_RMID,NULL);printf(key:%0x shmid:%d\n,key,shmid);sleep(10);*/return 0; } ​ 共享内存与管道不同是一旦申请好直接可以拿到内存的数据比管道读写数据快如同malloc一样并且不提供任何的同步性、原子性所以这也需要自己设计读写协议 总结 共享内存生命周期随内核进程间通信速度最快用户-内核而管道直接调用系统接口下至少要经历 用户-缓冲区-管道共享内存不提供任何同步机制、原子性等等是直接可以拿到内存数据共享内存申请时是以页为单位4kb不满页的会向上调整成页但是不会显示出来 内核相关的数据结构了解 ​ 共享内存不仅只限于两个进程间的通信还有可能多个进程进程之间多个内存间通信等等。为了防止这些进程之间都能正确的和对应的共享内存通信os就需要将共享内存进行管理只要提到管理就离不开“先描述在组织“。 怎么描述怎么组织 ​ 通过查看共享内存部分内核源码发现在申请共享内存时会有结构体来记录申请时时的所有详细信息如创建时间、申请大小、key值等等 再查看消息队列、信号量的在内核中的结构体 发现它们都有一个共同点第一个成员都是 struct ipc_perm ​ 所以在打印shmid时发现其好像是呈数组下标形式其实正是由于IPC通信的多样性内核的IPC资源结构类型不一样为了方便管理所以在每个资源的结构的第一个成员都设置成相同的。 ​ 而struct ipc_perm是记录一些比较关键的信息如key值那么这里也可以类似struct file* array[]一样有一个ipc_perm指针数组存每个IPC资源的中的ipc_perm所以shmid的作用就等同于文件描述符fd的作用。 ​ ipc_perm是第一个成员第一个成员的地址也是IPC的首地址可以通过强转类型的方式将每个IPC强转成ipc_perm再利用ipc_prem* 接收就可以拿到每个IPC中的ipc_prem了类似C中的切片
http://www.dnsts.com.cn/news/241866.html

相关文章:

  • 高校网站如何建设论文做网站上传图片
  • 网站后台密码文件济南天桥区做网站公司
  • 专业云南做网站中国建设网站官方网站
  • 个人做网站 优帮云wordpress怎么文章共享
  • 无锡网站制作推荐哈尔滨 网站开发
  • 京东的网站建设分析整站系统
  • 新手怎样自己做网站网络营销策划方案步骤
  • 网站后台账号密码忘记了怎么办企业网站keywords最多几个
  • 茂名 网站建设班级展示网站
  • 中信建设 官方网站广州电子商务网站建设费用
  • 开发一个网站的步骤深圳网络营销外包公司推荐
  • 做的非常好的网站案例wordpress修改侧边栏
  • ps做旅游网站wordpress博客优秀
  • 做相亲网站的红娘累吗建设 春风 摩托车官方网站
  • 如何修改网站后台时间百度浏览器app
  • 福州网站怎么做做网站联盟
  • 发电机出租技术支持 东莞网站建设网站首页添加标签
  • 人才网站开发文档谷歌网站
  • 网站开发怎么确定价格商城网站 搭建
  • seo网站排名优化wordpress 注册 填写密码
  • 做网站的人多吗自己做网站app
  • 淮北市做网站最好的公司dede网站地图文章变量
  • 宁波住房和建设局网站南京seo网络推广
  • 做网站好做吗网站建设那个比较好
  • 平湖做网站如何写推广软文
  • 深圳微信公众平台开发网站开发深圳百度总部
  • 网站右下角弹出广告代码wordpress添加
  • 整站下载工具软件成都网站建设成都app开发
  • 专业开发网站报价单帮客户做网站挣钱吗
  • 苏州网站公司排名前十建工在线