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

丹阳网站制作5118网站如何使用免费版

丹阳网站制作,5118网站如何使用免费版,网页设计比赛策划案,新手搭建网站一、概述 进程间通信(IPC,InterProcess Communication)是指在多个进程之间进行数据传输和共享的机制。在操作系统中,进程是运行中的程序的实例,每个进程都有自己的内存空间和资源。 进程间通信可以用于在不同的进程之间…

一、概述

        进程间通信(IPC,InterProcess Communication)是指在多个进程之间进行数据传输和共享的机制。在操作系统中,进程是运行中的程序的实例,每个进程都有自己的内存空间和资源。

        进程间通信可以用于在不同的进程之间传递数据、共享资源、进行协同工作等。常见的进程间通信方式有以下几种:

  1. 管道(Pipe):管道是一种半双工的通信方式,它是通过创建一个管道文件用于两个进程之间的通信。一个进程可以将数据写入管道,而另一个进程可以从管道中读取数据。

  2. 有名管道(Named Pipe):有名管道也是一种管道,不同之处在于它是一个带有名称的管道,可以用于多个进程之间的通信。

  3. 共享内存(Shared Memory):共享内存是一种进程间通信的高效方式,它允许多个进程访问同一块内存区域,从而实现数据共享。

  4. 消息队列(Message Queue):消息队列是一种按照先进先出(FIFO)原则进行数据传输的机制。进程可以将消息放入队列,而其他进程可以从队列中读取消息。

  5. 信号量(Semaphore):信号量是一个特殊的变量,用于控制多个进程之间的临界区访问。通过信号量可以实现进程的互斥和同步操作。

  6. 套接字(Socket):套接字是一种网络编程中常用的进程间通信方式,它可以在不同的主机之间进行数据传输和通信。

二、管道

1、用法

        管道(pipe)是一种在进程间通信中非常常用的机制,它可以将一个进程的输出(stdout)直接作为另一个进程的输入(stdin)。

        pipe()函数:创建管道使用,它的原型为:

int pipe(int pipefd[2]);

        该函数需要传入一个整型的数组,数组的长度必须是2。该函数会创建一个管道,并将管道的读写句柄分别存储在pipefd[0]和pipefd[1]中。pipefd[0]用于读取管道中的数据,pipefd[1]用于写入管道。

        常用函数有:

        read()函数:从管道中读取数据。其原型为:

ssize_t read(int fd, void *buf, size_t count);

        其中,fd是管道的读取句柄(即pipefd[0]),buf是存储读取数据的缓冲区,count是读取的最大字节数。该函数返回实际读取的字节数。如果从终端读取数据,fd 的值为 STDIN_FILENO。

        write()函数:向管道中写入数据。其原型为:

ssize_t write(int fd, const void *buf, size_t count);

        其中,fd是管道的写入句柄(即pipefd[1]),buf是待写入的数据的缓冲区,count是待写入的字节数。该函数返回实际写入的字节数。如果往终端写入数据,fd 的值为 STDOUT_FILENO。

        close()函数:关闭管道的读取或写入端。其原型为:

int close(int fd);

        其中,fd是待关闭的管道的句柄。

2、用例

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>int main(int argc, char const *argv[])
{pid_t pid;int pipefd[2];if (argc != 2){fprintf(stderr,"%s: 参数不够!\n",argv[0]);exit(EXIT_FAILURE);}//创建管道if (pipe(pipefd) == -1){perror("创建管道数据");exit(EXIT_FAILURE);}//创建子进程pid = fork();if (pid < 0){fprintf(stderr,"%s: 邀请新学员失败!\n",argv[0]);exit(EXIT_FAILURE);}else if (pid == 0){//读取管道数据并打印close(pipefd[1]);char str[100]={0};sprintf(str,"%d 读出数据",getpid());write(STDOUT_FILENO,&str,sizeof(str));char buf;while (read(pipefd[0],&buf,1)>0){write(STDOUT_FILENO,&buf,1);}write(STDOUT_FILENO,"\n",1);close(pipefd[0]);_exit(EXIT_SUCCESS);//直接退出不做任何操作}else{//写入管道数据,提供给子进程close(pipefd[0]);printf("%d 写入数据\n",getpid());write(pipefd[1],argv[1],strlen(argv[1]));close(pipefd[1]);waitpid(pid,NULL,0);}return 0;
}

        这个用例创建了一个子进程。随后父进程写入数据,子进程读取数据。

三、有名管道

1、用法

        有名管道(Named Pipe)是一种在操作系统中用于进程间通信的通道。它可以在不相关的进程之间传递数据。以下是对有名管道及常用函数的详细介绍。

        有名管道是一种特殊的文件,它以文件名的形式存在于文件系统中。与普通文件不同的是,有名管道允许不相关的进程之间进行通信。有名管道是以FIFO(先进先出)的方式传递数据,即先进入管道的数据首先被读取出来。有名管道可以用于在父进程和子进程之间传递数据,也可以用于不同进程之间的通信。

    mkfifo():创建一个新的有名管道。它的原型为:

int mkfifo(const char *pathname, mode_t mode)

        其中,pathname是管道的路径名,mode定义了管道的权限。该函数成功时返回0,失败时返回-1。

    open():打开有名管道以进行读取或写入操作。它的原型为:

int open(const char *pathname, int flags)

        其中,pathname是管道的路径名,flags定义了打开的方式和权限。该函数成功时返回文件描述符,失败时返回-1。

        其余函数如:read,write,close与管道用法一致。

        有名管道提供了一种简单的进程间通信方式,但也有一些限制。首先,它只适用于在同一计算机上的进程间通信。其次,有名管道是阻塞式的,即读取操作会一直等待直到有数据可读,写入操作会一直等待直到有空间可写。因此,在使用有名管道时要注意避免进程间出现死锁的情况。

2、用例

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>int main(int argc, char const *argv[])
{int fd;//有名管道创建完可重复使用,但推荐每次用完删除,下次重新创建char *pipe_path = "/tmp/myfifo";if(mkfifo(pipe_path,0644) != 0){perror("mkfifo");if (errno != 17)//不是文件已存在{exit(EXIT_FAILURE);}}fd = open(pipe_path,O_WRONLY);if(fd == -1){perror("open");exit(EXIT_FAILURE);}char buf[100];ssize_t read_num;//从终端写入数据到管道中while ((read_num = read(STDIN_FILENO,buf,100)) > 0){write(fd,buf,read_num);}if (read_num < 0){perror("read");close(fd);exit(EXIT_FAILURE);}printf("发送数据到管道完成,进程终止\n");close(fd);//清除管道//清除对应特殊文件if (unlink(pipe_path) == -1){perror("unlink");}return 0;
}
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>int main(int argc, char const *argv[])
{int fd;char *pipe_path = "/tmp/myfifo";// if(mkfifo(pipe_path,0644) != 0){//     perror("mkfifo");//     exit(EXIT_FAILURE);// }fd = open(pipe_path,O_RDONLY);if(fd == -1){perror("open");exit(EXIT_FAILURE);}char buf[100];ssize_t read_num;//读取管道信息while ((read_num = read(fd,buf,100)) > 0){write(STDOUT_FILENO,buf,read_num);}if (read_num < 0){perror("read");close(fd);exit(EXIT_FAILURE);}printf("接收管道数据完成,进程终止\n");close(fd);return 0;
}

        两个.c文件分别代表两个无关联的进程。一个从终端接收数据并将数据写入有名管道中,另一个从管道中接收数据并打印在终端。

四、共享内存

1、用法

        在C语言中,进程间通信(IPC)是实现不同进程之间数据交换和共享的重要方式之一。共享内存是一种高效的IPC机制,可以实现不同进程之间的数据共享。

        共享内存是一块由操作系统管理的内存区域,可以被多个进程同时访问。进程可以将共享内存映射到自己的地址空间中,从而可以直接读写该内存区域,实现数据共享。

        shm_open():该函数用于创建或打开一个共享内存对象。它的原型如下:

   int shm_open(const char *name, int oflag, mode_t mode);

        参数:
        name:共享内存对象的名称
        oflag:打开标志,用于指定打开方式和操作权限
        mode:权限位,用于指定该共享内存对象的操作权限
        返回值:共享内存对象的文件描述符,若打开或创建失败则返回-1。

        shm_unlink():该函数用于删除一个共享内存对象。它的原型如下:

   int shm_unlink(const char *name);

        参数:
        name:共享内存对象的名称
        返回值:成功返回0,失败返回-1。

        mmap():该函数用于将共享内存映射到进程的地址空间中。它的原型如下:

   void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

        参数:
        addr:指定映射的起始地址,通常设为NULL,让操作系统自动选择一个合适的地址。
        length:映射的长度,单位为字节。
        prot:映射内存区域的保护模式,如读、写、执行等。
        flags:映射的标志,用于指定映射方式和映射类型。
        fd:共享内存对象的文件描述符。
        offset:共享内存对象中的偏移量。
        返回值:映射成功时返回映射区域的起始地址,失败时返回MAP_FAILED。

    munmap():函数用于释放由mmap函数映射的内存区域。它的原型如下:

    int munmap(void *addr, size_t length);

        参数:

    addr:指向要释放的内存区域的起始地址。这个地址必须是mmap返回的地址,或者是页面大小的整数倍。

    length:要释放的内存区域的大小。

        返回值:成功时,返回0;失败时,返回-1,并设置errno

2、用例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/types.h>int main(int argc, char const *argv[])
{char *share;// 1.创建共享内存对象char shm_name[100]={0};sprintf(shm_name,"/letter%d",getpid());int fd;fd = shm_open(shm_name,O_RDWR | O_CREAT,0644);if (fd < 0){perror("shm_open");exit(EXIT_FAILURE);}// 2.设置共享内存对象大小ftruncate(fd,1024);// 3.内存映射share = mmap(NULL,1024,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if (share == MAP_FAILED){perror("mmap");exit(EXIT_FAILURE);}// 映射后关闭fd,不是释放close(fd);// 4.使用内存映射实现进程间的通讯pid_t pid = fork();if (pid < 0){perror("fork");exit(EXIT_FAILURE);}else if (pid == 0){strcpy(share,"hello,my name is liuyuhui\n");printf("子进程%d:发送完毕!\n",getpid());}else{waitpid(pid,NULL,0);printf("父进程 %d 接收到了子进程 %d 发送的消息: %s\n",getpid(),pid,share);// 5.释放映射区int re = munmap(share,1024);if (re == -1){perror("munmap");exit(EXIT_FAILURE);}}// 6.释放共享内存对象shm_unlink(shm_name);return 0;
}

        共享内存大致就分了这六步。这个例程实现的是父进程向共享内存中写入数据,子进程从共享内存中读出数据。

五、消息队列

1、用法

        在C语言中,进程间通讯是指两个或多个进程之间进行数据交换或共享资源的过程。消息队列是一种进程间通讯的方式,允许进程通过发送和接收消息来交换数据。

        mq_open():用于创建或打开一个消息队列。函数原型如下:

mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);

        参数:

        name:消息队列的名称。

        oflag:打开标志。可以是O_CREAT(如果消息队列不存在,则创建)和O_EXCL(与O_CREAT一起使用,确保创建新的消息队列)。

        mode:权限和创建文件时的权限位掩码(只有在创建消息队列时才使用)。attr:指向消息队列属性的指针。

        mq_unlink():用于删除一个已经命名的消息队列。函数原型如下:

int mq_unlink(const char *name);

        参数:

        name:消息队列的名称。

        clock_gettime():用于获取当前时间。函数原型如下:

int clock_gettime(clockid_t clk_id, struct timespec *tp);

        clk_id:时钟ID,可以是CLOCK_REALTIME(系统实时时间)或CLOCK_MONOTONIC(运行时间)。

        tp:保存时间的结构体指针。

        mq_timedsend():用于向消息队列发送消息,并可以设置发送超时时间。函数原型如下:

int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout);

        参数:

        mqdes:消息队列描述符。

        msg_ptr:指向发送消息的指针。

        msg_len:发送消息的长度。

        msg_prio:消息的优先级。

        abs_timeout:绝对时间,若超过该时间则发送超时。

        mq_timedreceive():用于从消息队列接收消息,并可以设置接收超时时间。函数原型如下:

ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio, const struct timespec *abs_timeout);

        参数:

        mqdes:消息队列描述符。

        msg_ptr:指向接收消息的指针。

        msg_len:接收消息的最大长度。

        msg_prio:接收到的消息的优先级。

        abs_timeout:绝对时间,若超过该时间则接收超时

2、用例

①:父子进程间通讯

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{struct  mq_attr attr;attr.mq_maxmsg=10;attr.mq_msgsize=100;attr.mq_flags=0;attr.mq_curmsgs=0;//创建消息队列char *mq_name = "/father_son"; mqd_t mqdes = mq_open(mq_name,O_RDWR|O_CREAT,0644,&attr);if (mqdes == -1){perror("mq_open");exit(EXIT_FAILURE);}//创建进程pid_t pid = fork();if (pid < 0){perror("fork");exit(EXIT_FAILURE);}else if (pid == 0){//子进程接收消息char read_buf[100];struct timespec time_info;//接受数据for (int i = 0; i < 10; i++){//清空并发送数据memset(read_buf,0,100);//设置等待时间clock_gettime(0,&time_info);time_info.tv_sec += 15;//接收消息if(mq_timedreceive(mqdes,read_buf,100,NULL,&time_info) == -1){perror("mq_timedreceive");}printf("子进程接收到消息:%s\n",read_buf);}}else{//父进程发送消息char send_buf[100];struct timespec time_info;for (int i = 0; i < 10; i++){//清空并发送数据memset(send_buf,0,100);sprintf(send_buf,"父进程发送的第 %d 条消息\n",(i+1));//获取当前时间clock_gettime(0,&time_info);time_info.tv_sec += 5;//发送消息if(mq_timedsend(mqdes,send_buf,strlen(send_buf),0,&time_info) == -1){perror("mq_timedsend");}printf("父进程休息1s\n");sleep(1);}}  //释放两次消息队列的引用close(mqdes);//清除一次消息队列if (pid > 0){mq_unlink(mq_name);}return 0;
}

②:不同进程间通讯

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{struct  mq_attr attr;attr.mq_maxmsg=10;attr.mq_msgsize=100;attr.mq_flags=0;attr.mq_curmsgs=0;//创建消息队列char *mq_name = "/p_c_mq"; mqd_t mqdes = mq_open(mq_name,O_RDWR|O_CREAT,0644,&attr);if (mqdes == -1){perror("mq_open");exit(EXIT_FAILURE);}char write_buf[100];struct timespec time_info;//不断接收控制台消息 发送到消息队列while (1){memset(write_buf,0,100);ssize_t read_count = read(STDIN_FILENO,write_buf,100);clock_gettime(0,&time_info);time_info.tv_sec += 5;if (read_count == -1){perror("read");continue;}else if (read_count == 0){//ctrl + d 退出时printf("EOF,exit...\n");char eof = EOF;if (mq_timedsend(mqdes,&eof,1,0,&time_info) == -1){perror("mq_timedsend");}break;}//正常发送if (mq_timedsend(mqdes,write_buf,strlen(write_buf),0,&time_info) == -1){perror("mq_timedsend");}printf("正常发送成功!\n");}//释放消息队列描述符close(mqdes);//清除消息队列  (消费者执行一次即可)// mq_unlink(mq_name);return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{struct  mq_attr attr;attr.mq_maxmsg=10;attr.mq_msgsize=100;attr.mq_flags=0;attr.mq_curmsgs=0;//创建消息队列char *mq_name = "/p_c_mq"; mqd_t mqdes = mq_open(mq_name,O_RDWR|O_CREAT,0644,&attr);if (mqdes == -1){perror("mq_open");exit(EXIT_FAILURE);}char read_buf[100];struct timespec time_info;//不断接收控制台消息 发送到消息队列while (1){memset(read_buf,0,100);clock_gettime(0,&time_info);time_info.tv_sec += 15;//正常接收if (mq_timedreceive(mqdes,read_buf,100,NULL,&time_info) == -1){perror("mq_timedreceive");}//判断是否结束if (read_buf[0] == EOF){printf("收到结束信息,准备退出...\n");break;}printf("正常接收成功,信息为:%s\n",read_buf);}//释放消息队列描述符close(mqdes);//清除消息队列mq_unlink(mq_name);return 0;
}

        需要注意的是因为公用同一片资源,所以在不同进程间通讯时接收方只需接收完消息后将消息队列清除掉即可,发送方不需要重复清除,也可避免接收方还没读取完消息队列的值就被发送方清除了消息队列。

http://www.mmbaike.com/news/48265.html

相关文章:

  • 如果有域名和空间怎么做网站专业代写文案的公司
  • 山东建设厅官方网站二建报名湖南靠谱的关键词优化哪家好
  • 宁波网站建设设计公司百度快速排名工具
  • 江苏建科建设监理有限公司网站天津优化公司
  • b2b电子商务平台简介seo自学网官方
  • 做网站阜阳培训心得体会1000字通用
  • 个人网站做镜像电池优化大师下载
  • 长白山网站学做管理最近最火的关键词
  • 网站弄论坛形式怎么做武汉网站营销seo方案
  • 网站功能策划seo服务包括哪些
  • 上海网站开发工程师东莞企业网站模板建站
  • 通过门户网站做单点登录SAP网络工程师培训一般多少钱
  • 劳务外包公司新乡网站优化公司
  • 常州做网站麦策电商安徽seo网络推广
  • 有了域名怎么做网站网站怎么建立
  • 建站工具 比较全球搜效果怎么样
  • 做网站需要那些东西汕头seo排名
  • 如何设计一个网站没灵感推广引流方法有哪些?
  • wordpress 标签 中文广州搜索seo网站优化
  • 南宁物流公司网站建设网页设计模板图片
  • 网站可以跟博客做互链吗百度提交网址入口
  • wordpress08影院seo视频教程我要自学网
  • 微信定制开发 网站开发壹起航网络推广的目标
  • 北京做网站商标的公司搜索词分析
  • 免费网站建设讯息百度视频
  • 医疗器械网上商城太原seo团队
  • 怎么做那些盗号网站百度优化关键词
  • css3 特效网站自媒体平台
  • 梅州网站建设求职简历成都网站建设公司
  • 建设网站人员百度seo快速排名优化