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

个人网站建设怎么赚钱wordpress图片目录

个人网站建设怎么赚钱,wordpress图片目录,动画设计就业前景,山东移动网站建设进程间通信 1. 进程间通信的概念2. 匿名管道pipe3. 命名管道FIFO4. 内存映射区 1. 进程间通信的概念 在Linux的环境下#xff0c;进程地址空间是相互独立的#xff0c;每个进程有着各自不同的用户地址空间。一个进程不能访问另一个进程中的内容#xff0c;要进行数据交换必… 进程间通信 1. 进程间通信的概念2. 匿名管道pipe3. 命名管道FIFO4. 内存映射区 1. 进程间通信的概念 在Linux的环境下进程地址空间是相互独立的每个进程有着各自不同的用户地址空间。一个进程不能访问另一个进程中的内容要进行数据交换必须要通过内核在内核中开辟块缓冲区一个进程将数据从用户空间拷贝到内核缓冲区中另一个进程从内核缓冲区中将数据读走。内核提供的这种机制称为进程间通信IPC。 在进程间完成数据传输需要借助操作系统提供的特殊方法比如文件、管道、FIFO、内存映射区、消息队列、信号、套接字等。如今常用的进程间通信主要有管道最简单、信号开销最小、内存映射区无血缘关系、本地套接字最稳定。 2. 匿名管道pipe 管道是一种最基本的进程间通信机制也称为匿名管道应用于有血缘关系的进程间进行通信。管道的本质是一块内核缓冲区内部使用的环形队列实现由两个文件描述符进行引用其中一个表示读端另一个表示写端。管道的数据从管道的写端流入管道从读端流出。当两个进程都死亡的时候管道也会自动消失。管道不管读端还是写端默认都是阻塞的。管道的默认缓冲区大小为4K可以使用ulimit -a命令获取大小。 管道的数据一旦被读走便不在管道中存在不可以反复读取。管道的数据只能在一个方向上流动如果需要实现双向流动则需要使用两个管道。匿名管道只能在有血缘关系的进程中使用。我们用pipe函数来创建管道。 pipe函数的原型如下 #include unistd.hint pipe(int pipefd[2]); // 创建管道 其中pipefd为管道写端和读端的文件描述符其中pipefd[0]为管道读端的文件描述符pipefd[1]为管道写端的文件描述符。当函数调用成功创建了管道返回0失败则返回-1并设置errno。 在使用匿名管道进行通信的时候一般是先用pipe函数创建管道再使用fork函数创建子进程。这样父子进程就具有了相同的文件描述符就会指向同一个管道。 在管道的通信中读写数据也是使用read和write。管道的示例代码如下 #include stdio.h #include stdlib.h #include unistd.h #include sys/wait.h #include string.hint main() {// 创建管道//int pipe(int pipefd[2]);int fd[2];int ret pipe(fd);if(ret 0){perror(pipe error);return -1;}// 创建子进程pid_t pid fork();if(pid 0){perror(fork error);return -1;}else if(pid 0){// 子进程关闭写端close(fd[1]);char buf[1024];memset(buf, 0x00, sizeof(buf));sleep(5);read(fd[0], buf, sizeof buf);printf(child: read over, pid [%d], fpid [%d], buf [%s]\n, getpid(), getppid(), buf);}else{// 父进程关闭读端close(fd[0]);write(fd[1], helloworld, strlen(helloworld));printf(father: write over, pid [%d], fpid [%d]\n, getpid(), getppid());pid_t wpid wait(NULL);printf(child [%d] is dead!\n, wpid);}return 0; }在shell中我们查询某一个进程的时候我们会使用ps -ef | grep --colorauto bash这里的|就是管道。我们使用父进程进程去执行ps -ef命令由于我们需要交给grep去作为输入所以在父进程中需要将输出重定向到管道的写端。子进程执行grep的时候会从输入进行读取内容因此我们需要将输入重定向到管道读端。重定向的时候需要使用dup2函数需要执行命令则需要使用execl和execlp函数示例程序如下 #include stdio.h #include stdlib.h #include sys/types.h #include fcntl.h #include sys/stat.h #include unistd.hint main() {// 创建管道int pipefd[2];int ret pipe(pipefd);if(ret 0){// 创建失败perror(pipe error);return -1;}// 创建子进程pid_t pid fork();if(pid 0){// 创建失败perror(fork error);return -1;}else if(pid 0){// 子进程关闭写端close(pipefd[1]);// 将标准输入重定向到管道读端dup2(pipefd[0], STDIN_FILENO);execlp(grep, grep, --colorauto, bash, NULL);perror(execlp error);}else {// 父进程关闭读端close(pipefd[0]);// 将标准输出重定向到管道写端dup2(pipefd[1], STDOUT_FILENO);execlp(ps, ps, -ef, NULL);perror(execlp error);}return 0; }当管道有数据的时候read可以正常读并返回读出来的字节数当管道没有数据的时候若写端全部关闭则read函数解出阻塞状态返回0相当于读文件读到了尾部。若写端没有关闭则read阻塞。 若读端全部关闭进行写操作的时候则管道会破裂进程终止内核会给当前进程发送SIGPIPE信号。若读端没有完全关闭缓冲区写满了则write会阻塞缓冲区没有满则可以继续write。 管道默认两端都是阻塞的若要设置为非阻塞则可以使用前面提过的fcntl函数。首先使用F_GETFL获取flags然后在添加O_NONBLOCK使用F_SETFL设置即可。当读端设置为非阻塞状态的时候会有以下四种情况 写端没有关闭管道中没有数据可读则read返回-1。写端没有关闭管道中有数据可读则read返回实际读到的字节数。写端已经关闭管道中有数据可读则read返回实际读到的字节数。写端已经关闭管道中没有数据可读则read返回0。 设置的流程为 int flags fcntl(fd[0], F_GETFL, 0); flags flags | O_NONBLOCK; fcntl(fd[0], F_SETFL, flags);除了前面使用的ulimit -a可以查看到管道缓冲区的大小之外也可以使用fpathconf函数该函数的原型为 #include unistd.hlong fpathconf(int fd, int name); 这个函数会根据name的参数设置返回文件描述符fd对应文件的配置内容。比如获取管道缓冲区则需要把name设置为_PC_PIPE_BUF。如下面查看管道的缓冲区大小。 printf(pipe size [%ld]\n, fpathconf(fd[0], _PC_PIPE_BUF)); printf(pipe size [%ld]\n, fpathconf(fd[1], _PC_PIPE_BUF));更多的name参数设置可以使用man fpathconf查询帮助文档。 3. 命名管道FIFO 使用pipe管道只能实现有血缘关系的两个进程间的通信那么对于两个没有血缘关系的进程又应该怎么实现呢则需要这一节的命名管道FIFO。 FIFO是Linux上基于文件类型的一种通信方式文件类型为p但是FIFO在磁盘上并没有数据块文件大小为0仅仅用于标识内核中的一条通道。进程可以通过read或者write函数去对这一条通道进行操作也就是内核缓冲区这样就实现了进程间的通信。 要使用命名管道就得先创建命名管道文件创建管道文件使用mkfifo函数该函数的原型为 #include sys/types.h#include sys/stat.hint mkfifo(const char *pathname, mode_t mode); 其中参数第一个pathname表示管道的路径名mode表示权限使用一个三位八进制数表示。创建成功函数返回0创建失败则函数返回-1并设置errno。 FIFO严格遵守先进先出的规则也就是对于管道的读总是从管道的开始处返回数据而对于管道的写则是添加到末尾。因此命名管道不支持使用lseek等对文件定位的操作。 使用FIFO完成进程间通信的示意图如下 既然是两个进程也就是说两个进程中的程序都需要打开管道也就是需要找到文件。若写进程没有打开就去使用读进程则可能因为管道的文件不存在而报错。因此我们在使用管道或者创建管道之前要先判断文件是否存在。这个可以使用access函数实现该函数的原型为 #include unistd.hint access(const char *pathname, int mode); 该函数的第一个参数pathname是文件的路径第二个参数mode表示要测试的模式有四个参数可以传分别为 F_OK 文件存在R_OK有读权限W_OK有写权限X_OK有执行权限 当有对应的权限或者文件存在的时候该函数的返回值为0若没有对应权限或者文件不存在则该函数返回-1。 接下来我们实现两个无血缘关系之间的进程间通信。代码如下 fifo_write.c #include stdio.h #include stdlib.h #include string.h #include unistd.h #include sys/stat.h #include sys/types.h #include fcntl.h// FIFO 写进程 int main() {// 创建FIFO文件// int access(const char *pathname, int mode);int ret access(./myfifo, F_OK);if(ret 0){// int mkfifo(const char *pathname, mode_t mode);ret mkfifo(./myfifo, 0777);if(ret 0){perror(mkfifo error);return -1;}}// 打开FIFOint fd open(./myfifo, O_RDWR);if(fd 0){perror(open error);return -1;}// 传输数据char buf[1024] hello world;write(fd, buf, strlen(buf));sleep(1);// 关闭FIFOclose(fd);return 0; } fifo_read.c #include stdio.h #include stdlib.h #include string.h #include unistd.h #include sys/types.h #include sys/stat.h #include fcntl.h// FIFO 读进程端 int main() {// 判断创建FIFOint ret access(./myfifo, F_OK);if(ret 0){int ret mkfifo(./myfifo, 0777);if(ret 0){perror(mkfifo error);return -1;}}// 打开FIFOint fd open(./myfifo, O_RDWR);if(fd 0){perror(open error);return -1;}// 接收数据char buf[1024];memset(buf, 0x00, sizeof buf);read(fd, buf, sizeof buf);printf(%s\n, buf);// 关闭FIFOclose(fd);return 0; } 在上述代码中只要运行不管是读进程还是写进程先运行只要写进程没有往管道中写数据读进程都会阻塞在read处。直到写进程调用write函数往管道中写数据之后读进程才会读出来管道中的数据输出。 4. 内存映射区 内存映射区是将一个磁盘文件与内存空间的一个缓冲区向映射。当我们在缓冲区中读取数据的时候就相当于在文件中读取相应的字节。若我们向缓冲区中写数据则会把数据写入对应的文件之中。这样就可以在不使用read函数和write函数啊的情况下使用指针完成IO操作。 映射这个过程可以使用mmap函数实现。解除映射可以使用munmap实现。函数的原型以及参数如下 #include sys/mman.h// 函数作用: 建立存储映射区// 返回值: 成功返回创建的映射区首地址// 失败 返回MAP_FAILED宏 实际上就是(void *)-1// 参数: addr: 指定映射的起始地址通常设为NULL由系统指定// length: 映射到内存的文件长度// prot: 映射区的保护方式最常用的有// PROT_READ 读// PROT_WRITE 写// PROT_READ | PORT_WRITE 读写// flags: 映射区的特性可以设置以下// MAP_SHARED 写入映射区的数据会写回文件且允许// 其它映射改文件的进程共享。// MAP_PRIVATE 对映射区的写入操作会产生一个映射区的复// 制对此区域所做的修改不会写回原文件。// MAP_ANONYMOUS 匿名映射区需要结合MAP_SHARED使用。// fd: 代表要映射的文件由open函数返回的文件描述符// offset: 以文件开始出的偏移量,必须是4K的整数倍通常为0表示// 从文件头开始映射void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);// 函数作用: 释放由mmap函数建立的存储映射区// 返回值 成功返回0失败返回-1并设置errno// 参数 addr: 调用mmap函数成功返回的映射区首地址// length: 映射区的大小int munmap(void *addr, size_t length);需要注意到的是mmap函数不能开辟长度为0的存储映射区。在使用mmap函数创建映射区的过程中隐含着一次对映射文件的读操作将文件读取到映射区。当我们将flags设置为MAP_SHARED的时候要求映射区的权限应该小于或者等于文件打开的权限这是出于对映射区的保护。而对于MAP_PRIVATE则是没有这个必要因为mmap中的权限是对内存的限制。 在映射区建立之后映射区的释放是与文件的关闭无关的所以在映射区建立之后就可以关闭文件。在创建映射区的时候使用mmap函数常常会出现总线错误通常是因为共享文件存储空间大小引起的。所以创建映射区的时候出错的概率比较高因此一定要检查函数的返回值确保映射区建立成功了再进行后续的操作。使用munmap函数的时候传入的地址一定要是mmap函数的返回值一定不要改变指针的指向。其中函数的参数中offset也是需要注意的不能随便指定必须要是4K的整数倍才行。 下面给出一个关于关于有血缘关系的进程间的通信示例。 //使用mmap完成有血缘关系进程间的通信 #include stdio.h #include stdlib.h #include string.h #include sys/types.h #include sys/stat.h #include sys/wait.h #include sys/mman.h #include unistd.h #include fcntl.hint main() {//使用mmap函数建立共享映射区//void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);int fd open(test.log, O_RDWR);if(fd 0){perror(open error);return -1;}int len lseek(fd, 0, SEEK_END);void *addr mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if(addr MAP_FAILED){perror(mmap error);return -1;}close(fd);//创建子进程pid_t pid fork();if(pid 0){perror(fork error);return -1;}else if(pid 0){//子进程sleep(2);char *p (char *)addr;printf([%s]\n, p);}else{//父进程memcpy(addr, hello world, strlen(hello world));wait(NULL);}return 0; } 共享存储映射区也可以用于没有血缘关系的两个进程。 写进程 // 使用mmap完成没有血缘关系的进程间的通信 #include stdio.h #include stdlib.h #include string.h #include unistd.h #include fcntl.h #include sys/stat.h #include sys/types.h #include sys/mman.h// 写进程 int main() {// 使用mmap函数建立共享映射区int fd open(test.log, O_RDWR);if(fd 0){perror(open error);return -1;}int len lseek(fd, 0, SEEK_END);// 建立共享映射区void *addr mmap(NULL, len, PROT_WRITE, MAP_SHARED, fd, 0);if(addr MAP_FAILED){perror(mmap error);return -1;}close(fd);memcpy(addr, Good morning, strlen(Good morning));return 0; } 读进程 // 使用mmap完成没有血缘关系的两个进程间的通信 #include stdio.h #include stdlib.h #include string.h #include unistd.h #include fcntl.h #include sys/types.h #include sys/stat.h #include sys/mman.h// 读进程端 int main() {// 使用mmap函数建立共享映射区int fd open(test.log, O_RDONLY);if(fd 0){perror(open error);return -1;}int len lseek(fd, 0, SEEK_END);// 建立共享映射区void *addr mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);if(addr MAP_FAILED){perror(mmap error);return -1;}char *p (char *)addr;printf([%s]\n, p);return 0; } 上面的共享存储映射区都是有名字的我们也可以创建匿名的共享存储映射区。匿名映射区是不需要使用文件去创建的因此没有血缘关系的两个进程不能使用匿名映射区通信。在使用匿名共享映射区的时候文件的描述符一般传为-1。关于匿名共享映射区的示例代码如下 // 建立匿名共享映射区 #include stdio.h #include stdlib.h #include unistd.h #include string.h #include sys/stat.h #include sys/types.h #include sys/wait.h #include sys/mman.h #include fcntl.hint main() {void *addr mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);if(addr MAP_FAILED){perror(mmap error);return -1;}pid_t pid fork();if(pid 0){perror(fork error);return -1;}else if(pid 0){sleep(2);char *p (char *)addr;printf([%s]\n, p);}else{memset(addr, 0x00, 4096);memcpy(addr, hello world, strlen(hello world));wait(NULL);}return 0; } 后续博客关于函数原型以及作用均以注释的形式写在代码中以便直观
http://www.hkea.cn/news/14306311/

相关文章:

  • 有那个网站做简历模板颜色搭配对网站重要性
  • 在线crm合肥网站优化推广方案
  • 动画网站源码工程在哪个网站做推广比较合适
  • 兴化网站网站建设泉州网站建设推广服务
  • 做一的同志小说网站有哪些html情人节给女朋友做网站
  • 新网站排名优化西宁微网站建设多少钱
  • 用新华做网站名是否侵权wordpress数据库排序规则
  • 现在的网站怎样做推广个人站长做哪些网站好
  • 办文明网站 做文明网民活动菏泽网站建设优惠臻动传媒
  • 网站建立不安全福州
  • 网站架构文案一般的网络课程设计应包括课程设计和
  • 自己做网站好还是购买网站好电商网站怎么做seo
  • 株洲seo优化报价网络营销推广及优化方案
  • 网站开发需求问卷嘉兴企业网站排名
  • wamp 设置多个网站销售管理软件crm
  • 雄安免费网站建设方案上海人才网赶集网
  • 诚信通旺铺网站建设app界面设计尺寸规范
  • 学校的网站的代码模板免费的网站开发工具
  • 太平洋网站建设免费领手机 网站
  • 泸州做网站公司wordpress新闻源码
  • 无锡市住房与城乡建设局网站国外域名注册商哪家好
  • 深圳上市公司网站建设公司都有哪些电商平台
  • 陕西省城乡建设厅网站跨境电商app开发
  • 网站开发需要哪些人怎么分工营销型网站建设 深圳信科
  • 行政机关网站建设的意义美工招聘平台
  • flash做企业网站宣传片网站开发信息文档
  • 海通建设集团有限公司网站资源下载网
  • 同城购物网站怎么做简短干净三字公司起名
  • 开公司网站创建费用新媒体营销策划
  • 关于网站建设分类wordpress 新闻系统