精华内容
下载资源
问答
  • 2021-05-12 14:22:02

    《Linux进程通信实验报告》由会员分享,可在线阅读,更多相关《Linux进程通信实验报告(5页珍藏版)》请在人人文库网上搜索。

    1、Linux进程通信实验报告一、 实验目的和要求1. 进一步了解对进程控制的系统调用方法。2. 通过进程通信设计达到了解UNIX或Linux系统中进程通信的基本原理。二、 实验内容和原理1. 实验编程,编写程序实现进程的管道通信(设定程序名为pipe.c)。使用系统调用pipe()建立一条管道线。而父进程从则从管道中读出来自于两个子进程的信息,显示在屏幕上。要求父进程先接受子进程P1发来的消息,然后再接受子进程P2发来的消息。2. 可选实验,编制一段程序,使其实现进程的软中断通信(设定程序名为softint.c)。使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键。

    2、盘上来的中断信号(即按Del键),当父进程接受这两个软中断的其中一个后,父进程用系统调用kill()向两个子进程分别发送整数值为16和17的软中断信号,子进程获得对应软中断信号后分别输出相应信息后终止。三、 实验环境一台安装了Red Hat Linux 9操作系统的计算机。四、 实验操作方法和步骤进入Linux操作系统,利用vi编辑器将程序源代码输入并保存好,然后打开终端对程序进行编译运行。五、 实验中遇到的问题及解决六、 实验结果及分析基本实验可选实验七、 源代码Pipe.c#includestdio.h#includeunistd.hmain()int i,j,fd2;char S100;。

    3、pipe(fd);if(i=fork=0)sprintf(S,child process 1 is sending a message n);write(fd1,S,50);sleep(3);return;if(j=fork()=0)sprintf(S,child process 2 is sending a message n);write(fd1,S,50);sleep(3);return;elsewait(0);read(fd0,S,50);printf(%s,S);read(fd0,S,50);printf(%s,S);return;Softint.c#includestdio.h#i。

    4、ncludeunsitd.hmain()int i,j,fd2;char S100;pipe(fd);if(i=fork=0)sprintf(S,child process 1 is sending a message n);write(fd1,S,50);sleep(3);return;if(j=fork()=0)sprintf(S,child process 2 is sending a message n);write(fd1,S,50);sleep(3);return;elsewait(0);read(fd0,S,50);printf(%s,S);read(fd0,S,50);printf(%s,S);return。

    更多相关内容
  • 实验六Linux 进程间通信2 4 课时 实验目的 理解进程通信原理掌握进程中信号量共享内存消息队列相关的函数的使用 实验原理 Linux 下进程通信相关函数除上次实验所用的几个还有 信号量 信号量又称为信号灯它是用来协调...
  • 实验报告详细描述了进程间通信的实现原理,使用管道以及信号实现进出那个间通信,附有源代码实现。
  • 这个文档是基于有名管道进程间通信的一些实验,可以从本质上理解进程间通信的有名管道的机理。并附有源码,可以自己复制下来,进行调试。
  • 实验六Linux进程间通信24课时 实验目的 理解进程通信原理掌握进程中信号量共享内存消息队列相关的函数的使用 实验原理 Linux下进程通信相关函数除上次实验所用的几个还有 信号量 信号量又称为信号灯它是用来协调不同...
  • 这是一份关于进程间通信实验报告的源代码文件
  • 3.(3)进程间信号通信 4.(4)进程的管道通信 编写程序,创建两个子进程。当此程序运行时,系统中有一个父进程和两个子进程。父进程在屏幕上显示“Parent”,子进程分别在屏幕上显示“Child1”和“Child2”。 ...
  • 编写一段程序,实现进程的管道通信。 使用系统调用pipe( )建立一条管道,创建两个子进程P1和P2。让P1和P2分别向管道各写一句话: child process P1 is sending messages! child process P2 is sending messages! 父...
  • 实验2 Linux软中断通信 1.实验目的 通过本实验掌握软中断的基本原理掌握中断信号的使用进程的创建以及系统计时器的使用 2.实验内容上交的实验2统一取名为test2) 由父进程创建两个子进程通过终端输入Crtl+\组合键向父...
  • 实验六:进程间通信实验目的:学会进程间通信方式:无名管道,有名管道,信号,消息队列,实验要求:在父进程中创建一无名管道,并创建子进程来读该管道,父进程来写该管道在进程中为 SIGBUS注册处理函数,并向该...

    实验六:进程间通信

    实验目的:

    学会进程间通信方式:无名管道,有名管道,信号,消息队列,

    实验要求:

    在父进程中创建一无名管道,并创建子进程来读该管道,父进程来写该管道

    在进程中为 SIGBUS注册处理函数,并向该进程发送SIGBUS信号

    创建一消息队列,实现向队列中存放数据和读取数据

    实验器材:

    软件:安装了 Linux的vmware虚拟机

    硬件:PC机一台

    实验步骤:

    (一)无名管道的使用

    1编写实验代码 pipe rw.c

    #in elude

    #in elude

    #in elude

    #i nclude

    #in elude

    #i nclude

    int mai n()

    {

    int pipe_fd[2];〃管道返回读写文件描述符

    pid_t pid;

    char buf_r[100];

    char* p_wbuf;

    int r_num;

    memset(buf_r,0,sizeof(buf_r));〃 将 buf_r 初始化

    char str1[]= "parent writel holle ” ”

    char str2[]= "parent write2 pipe”n”

    r_num=30;

    /*创建管道*/

    if(pipe(pipe_fd)<0)

    {

    prin tf("pipe create error'n ”);

    return -1;

    }

    /*创建子进程*/

    if((pid=fork())==0)〃子进程执行代码

    {

    〃1、子进程先关闭了管道的写端

    close(pipe_fd[1]);

    〃2、让父进程先运行,这样父进程先写子进程才有内容读

    sleep(2);

    〃3、读取管道的读端,并输出数据

    if(read(pipe_fd[O],buf_r, r_num)<0)

    {

    printf( read error!");

    exit(-1);

    }

    printf( %s\n",buf_r);

    〃4、关闭管道的读端,并退出

    close(pipe_fd[1]);

    }

    else if(pid>0) //父进程执行代码

    {

    〃1、父进程先关闭了管道的读端

    close(pipe_fd[0]);

    〃2、向管道写入字符串数据

    p_wbuf= &str1;

    write(pipe_fd[1],p_wbuf,sizof(p_wbuf));

    p_wbuf= &str2; write(pipe_fd[1],p_wbuf,sizof(p_wbuf));

    〃3、关闭写端,并等待子进程结束后退出

    close(pipe_fd[1]);

    }

    return 0;

    }

    /***********************

    #in clude

    #in clude

    #in clude

    #i nclude

    #in clude

    #i nclude

    int mai n()

    {

    int pipe_fd[2];//管道返回读写文件描述符

    pid_t pid;

    char buf_r[100];

    char* p_wbuf;

    int r num;

    memset(buf_r,0,sizeof(buf_r));〃 将 buf_r 初始化

    char str1[]="holle";

    char str2[]="pipe";

    r_num=10;

    /*创建管道*/

    if(pipe(pipe_fd)<0)

    {

    prin tf("pipe create error'n ”); return -1;

    }

    /*创建子进程*/

    if((pid=fork())==0)〃子进程执行代码

    {

    close(pipe_fd[1]);//1、子进程先关闭了管道的写端

    〃2、让父进程先运行,这样父进程先写子进程才有内容读

    〃3、读取管道的读端,并输出数据

    if(read(pipe_fd[0],buf_r, r_n um)<0)

    {

    prin tf("read1 error!");

    exit(-1);

    }

    prin tf("\npare nt write1 %s!",buf_r);

    sleep(1);

    if(read(pipe_fd[0],buf_r, r_n um)<0)

    {

    prin tf("read2 error!");

    exit(-1);

    }

    prin tf("\npare nt write2 %s!",buf_r);

    close(pipe_fd[1]);//4、关闭管道的读端,并退出

    exit(1);

    //prin tf("child error!");

    展开全文
  • 操作系统实验完整报告 在Linux系统中使用系统调用fork()创建两个子进程,使用系统调用pipe()建立一个管道,两个子进程分别向管道各写一句话: Child process 1 is sending a message! Child process 2 is sending a...
  • (1) 熟悉并掌握管道机制,并实现进程间通信 (2) 熟悉并掌握共享内存机制,并实现进程间通信 二、实验内容 任务一: (1)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析。 (2)...

    理论知识

    Linux——Linux C语言编程基础知识

    Linux——进程通信

    一、实验目的

    (1) 熟悉并掌握管道机制,并实现进程间通信

    (2) 熟悉并掌握共享内存机制,并实现进程间通信

    二、实验内容

    任务一:

    (1)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析。

    (2)编写程序:父进程利用管道将一字符串交给子进程处理。子进程读字符串,将里面的字符反向后再交给父进程,父进程最后读取并打印反向的字符串。

    任务二:

    (1)阅读例2的程序,运行一次该程序,然后用ipcs命令查看系统中共享存储区的情况,再次执行该程序,再用ipcs命令查看系统中共享内存的情况,对两次的结果进行比较,并分析原因。最后用ipcrm命令删除自己建立的共享存储区。

    1、ipcs命令的作用:用于查看系统中共享存储区,消息队列和信号量的情况。如下图:

    [x02620101@localhost x02620101]$ ipcs
    
    ------ Shared Memory Segments --------
    key        shmid      owner      perms      bytes     nattch  status
    0x0000000f 262145     x02620101 644        1000       0
    0x00000000 294914     x02620101 644        20         0
    
    ------ Semaphore Arrays --------
    key        semid      owner      perms      nsems
    
    ------ Message Queues --------
    key        msqid      owner    perms      used-bytes   messages
    

    2、ipcrm命令的作用:用于删除系统中存在的共享存储区,消息队列等。如:

    ipcrm  -M key 表示根据关键字删除共享存储区

    ipcrm -m id表示根据标识符删除共享存储区

    ipcrm -Q key表示根据关键字删除消息队列

    ipcrm -q id表示根据标识符删除消息队列

    (2)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。运行结束后可以用ctrl+c结束程序1的运行。

    注:把&加在一个命令的最后,可以把这个命令放到后台执行 ,如gftp &,

    (3)编写程序:使用系统调用shmget(),shmat(),shmdt(),shmctl(),编制程序。要求在父进程中生成一个30字节长的私有共享内存段。接下来,设置一个指向共享内存段的字符指针,将一串大写字母写入到该指针指向的存贮区。调用fork()生成子进程,让子进程显示共享内存段中的内容。接着,将大写字母改成小写,子进程修改共享内存中的内容。之后,子进程将脱接共享内存段并退出。父进程在睡眠5秒后,在此显示共享内存段中的内容(此时已经是小写字母)。

    注:

    需要包含头文件:

    #include <sys/wait.h>

    举例:

    sleep(1);   休眠一秒

    三、代码及运行结果分析

    任务一:

    (1)

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    int main()
    {
            int x,fd[2];
            char buf[30],s[30];
            pipe(fd);
            while ((x=fork())==-1);
            if (x==0)
            {
                    close(fd[0]);
                    printf("Child Process!\n");
                    strcpy(buf,"This is an example\n");
                    write(fd[1],buf,30);
                    exit(0);
                                               }
            else{
                    close(fd[1]);
                    printf("Parent Process!\n");
                    read(fd[0],s,30);
                    printf("%s\n",s);
            }
            return 0;
    }

     

    分析: 

    调用pipe(fd);创建一个管道后,接着调用fork()函数产生两个进程,首先开始执行子进程,关闭管道出口,通过管道入口向管道中写入内容。父进程中,管道入口关闭,通过管道出口端从管道中读取之前写入内容,最后输出出来。

    (2)

    #include<stdio.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdlib.h>
    int main(){
            int x,count,left,right,temp,fd[2],fe[2];
            char c,buf[30],s[30];
            pipe(fd);
            pipe(fe);
            printf("please input a line of char:\n");
            scanf("%s",buf);
            while((x=fork())==-1);
            if(x==0){
                    close(fd[0]);
                    close(fe[1]);
                    printf("Child Process!\n");
                    write(fd[1],buf,30);
                    read(fe[0],buf,30);
                    printf("%s\n",buf);
                    exit(0);
            }else{
                    close(fd[1]);
                    close(fe[0]);
                    count=0;
                    do{
                            read(fd[0],&c,1);
                            s[count++]=c;
                    }while(c!='\0');
                    printf("Parent Process!\n");
                    printf("%s\n",s);count-=2;
                    for(left=0,right=count;left<=count/2;left++,right--){
                            temp=s[left];
                            s[left]=s[right];
                            s[right]=temp;
                    }
                    write(fe[1],s,30);
                    wait(0);
            }
    }

     

    任务二:

    (1)

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    
    int main(){
            key_t key=200; /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/
            int shmid_1,shmid_2;
            if ((shmid_1=shmget(key,1000,0644|IPC_CREAT))==-1){
                    perror("shmget shmid_1");exit(1);
            }
            printf("First shared memory identifier is %d\n",shmid_1);
            if ((shmid_2=shmget(IPC_PRIVATE,20,0644))==-1){
                    perror("shmget shmid_2");exit(2);
            }
            printf("Second shared memory identifier is %d\n",shmid_2);
            exit(0);
            return 0;
    }

    分析: 

    成功,返回共享内存段的标识符,内核中用于唯一的标识一个对象。对存在于内核存贮空间中的每个共享内存段,内核均为其维护着一个数据结构shmid_ds。 失败,返回-1,设置errno。 

    ①第一个参数key(键值)用来创建IPC标识符,shmget()返回的标识符与key值一一对应,不同的key值返回不同的标识符。 

    ②第二个参数size,决定了共享内存段的大小(若访问已存在的内存段,该参数可设为0)。有最大字节数的限制 

    ③第三个参数shmflag,用于设置访问权限及标识创建条件。 

    对两次的结果进行比较:

    两次运行结束后的 第二个共享标识符是不一样的。在用ipcs查看时,共享内存段中的关键字,共享内存标识符,访问权限,字节等都是不一样的。

    (2)

    程序1:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #define SHMKEY 200  /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/
    #define K  1024
    int shmid;
    int main (){
            int i,*pint;
            char *addr;
            //extern int shmat();
            extern cleanup();
            for(i=0;i<20;i++) signal(i,cleanup);
            shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */
            addr=shmat(shmid,0,0);/*挂接,并得到共享区首地址 */
            printf ("addr 0x%x\n",addr);
            pint=(int *)addr;
            for (i=0;i<256;i++) *pint++=i;
            pause();/*等待接收进程读 */
    }
    cleanup()
    {
            shmctl(shmid,IPC_RMID,0);
            exit(0);
    }

    程序2: 

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #define SHMKEY 200  /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/
    #define K  1024
    int shmid;
    int main ()
    {
            int i,*pint;
            char *addr;
            //extern char * shmat ();
            shmid=shmget(SHMKEY,8*K,0777);/*取共享区SHMKEY的id */
            addr=shmat(shmid,0,0);/*连接共享区*/
            pint=(int *)addr;
            for (i=0;i<256;i++)
                    printf("%d\n",*pint++);/*打印共享区中的内容*/
    }

    分析: 

    首先系统通过调用shmctl对预定义的shmid指向的内存段进行删除操作,防止冲突,接着系统调用shmget创建一个16*1024字节的共享内存段,成功返回共享内存段的标识符给shmid,系统再次调用shmat连接内存段,返回该共享内存段连接到调用进程地址空间上的地址addr。

    程序1后台运行时,该程序开始执行,系统调用shmget创建一个8*1024字节的共享内存段,再通过调用shmat挂接内存段,由系统选择挂接地址,最终输出转换后的挂接地址。最后输出前255的内容。共享存储区机制只为通信进程提供了访问共享存储区的操作条件,而对通信的同步控制则要依靠信号量机制等才能完成。

    (3)

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #define SHMKEY 200
    #define K 1024
    int shmid_1,shmid_2;
    int main ()
    {
            int x,y,i,*pint;
            char *addr_1,*addr_2;
            char words[26]={'A','B','C','D','E','F','G','H','I','J',
            'K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','X'};
            shmid_1=shmget(SHMKEY,30*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */
            addr_1=shmat(shmid_1,0,0);/*挂接,并得到共享区首地址*/
            pint=(int *)addr_1;
            printf ("addr_1 0x%x\n",addr_1);
            for (i=0;i<26;i++) {
                    *pint=words[i];
                    pint++;
            }
            while((x=fork())==-1);
            if(x==0){
                    shmid_2=shmget(SHMKEY,30*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */
                    addr_2=shmat(shmid_2,0,0);/*挂接,并得到共享区首地址*/
                    pint=(int *)addr_2;
                    for(i=0;i<26;i++){
                            printf("%c ",*pint);
                            *pint=*pint+32;
                            pint++;
                            if(i==25)printf("\n");
                    }
                    y=shmdt(addr_2);
                    exit(0);
            }else{
                    sleep(5);
                    pint=(int *)addr_1;
                    for(i=0;i<26;i++){
                            printf("%c ",*pint);
                            pint++;
                            if(i==25)printf("\n");
                    }
            }
    }
    

    四、实验心得

    通过本次实验了解了管道进程间通信形式,掌握利用管道进行进程通信的程序设计,管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道; 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统。数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。基本达到了本次实验的要求。另外,对于共享内存通信的工作机制也有了一定的了解,掌握线程与进程在组成成分上的差别,以及与其相适应的通讯方式和应用目标。知道了操纵共享内存共有shmget()、shmat()、shmdt()、shmctl()4个系统调用。ipcs命令的作用:用于查看系统中共享存储区,消息队列和信号量的情况,ipcrm命令的作用:用于删除系统中存在的共享存储区,消息队列。也让我对管道及共享区的作用和用法,以及对操作系统中各进程之间的通信和协同作用等方面有了更深的了解。总之,本次实验自己收获了很多。

     

    参考文章

    实验三、进程通信(一) ——管道及共享内存

    实验三、 操作系统(OS)--进程通信(管道及共享内存)

    实验三 进程通信(一)

    linux c 休眠函数sleep usleep

    Linux后台进程管理以及ctrl+z(挂起)、ctrl+c(中断)、ctrl+\(退出)和ctrl+d(EOF)的区别

     

    展开全文
  • 实验内容1:进程间通信—消息机制 编译运行课件 Lecture 09 例程代码: Algorithms 9-1 ~ 9-2. 修改代码,观察在 msgsnd 和 msgrcv 并发执行情况下消息队列的变化情况。 实验内容2: 仿照 alg.8-4~8-6...

    操作系统实验报告8

    实验内容

    • 实验内容1:进程间通信—消息机制

      • 编译运行课件 Lecture 09 例程代码:

        • Algorithms 9-1 ~ 9-2.

        • 修改代码,观察在 msgsnd 和 msgrcv 并发执行情况下消息队列的变化情况。

    • 实验内容2:

      • 仿照 alg.8-4~8-6,编制基于 POSIX API 的进程间消息发送和消息接收例程。

    实验环境

    • 架构:Intel x86_64 (虚拟机)
    • 操作系统:Ubuntu 20.04
    • 汇编器:gas (GNU Assembler) in AT&T mode
    • 编译器:gcc

    技术日志

    实验内容1:进程间通信—消息机制

    • 验证实验Algorithms 9-1 ~ 9-2

    分析:

    实验内容原理:

    消息队列是在消息的传输过程中保存消息的容器,消息被发送到队列中,消息队列管理器在将消息从它的源中继到它的目标时充当中间人。队列的主要目的是提供路由并保证消息的传递;如果发送消息时接收者不可用,消息队列会保留消息,直到可以成功地传递它,可以传送多种类型的数据,但是有大小限制。

    首先,进程9-1 msgsnd会根据一个IPC 键值使用msgget()函数,创建一个消息队列,然后使用msgctl()函数获取和设置消息队列的属性,再使用msgsnd()函数向消息队列中发送信息,这些消息每条包含一个消息类型号和消息内容,进程9-1 msgsnd结束后,发送的消息还留在消息队列中,并没有被释放。

    然后,进程9-2 msgrcv会根据同一个IPC 键值使用msgget()函数获取之前创建的同一个消息队列,然后使用msgctl()函数获取和设置消息队列的属性,再使用msgrcv()函数从消息队列中根据消息类型号获取信息,每次将选择的消息类型号的所有信息获取出来,如果消息类型号为0,那么将消息队列中的全部信息获取出来,并弹出提示是否要删除这个空的消息队列,若是则该消息队列被释放,当消息队列中还有信息时,进程9-2 msgrcv结束并不会释放消息队列,消息队列中的消息也不会被删除。

    首先执行文件alg.9-1-msgsnd.c

    执行程序命令:

    gcc alg.9-1-msgsnd.c
    ./a.out /home/ubuntu/myshm
    

    执行截图:

    实现细节解释:

    首先进入一个条件判断语句,如果argc < 2,那么说明编译命令出错,打印Usage: ./a.out pathname提示我们补全路径名,以便之后根据文件信息使用ftok()函数获得IPC 键值,并返回EXIT_FAILURE表示异常退出。

    如果编译命令正确,那么继续往下执行,如果获取文件信息失败,进行异常处理,使用creat(pathname, O_RDWR)函数在原来文件路径处创建一个新的同名可读可写文件,并把creat()函数的返回值赋给ret,如果ret为-1,说明创建失败,使用宏定义ERR_EXIT("creat()")打印错误信息和原因,否则打印语句shared file object created,说明创建成功。

    接着,通过ftok(pathname, 0x27)获得一个IPC 键值,ftok()函数会根据参数pathname的文件信息和序号参数0x27的计划编号合成IPC key键值并赋给变量key,从而避免用户使用key值时发生冲突。如果key值小于0,说明ftok()失败,使用宏定义ERR_EXIT("ftok()")打印错误信息,否则打印IPC key = 0x后面跟生成的IPC 键值,显示生成的IPC 键值。

    接下来,使用msgget((key_t)key, 0666 | IPC_CREAT)创建一个新的或者打开一个已经存在的消息队列,这个消息队列与key值相对应,并把队列标识符作为返回值赋给变量msqid,其中参数(key_t)key为转换为(key_t)类型的之前通过ftok()函数得到的IPC键值,参数(0666 | IPC_CREAT)表示进程对消息队列可读可写,IPC_CREAT表示如果消息队列不存在,便创建消息队列,否则就进行打开操作。

    如果msqid的值为-1,说明msgget()失败,使用宏定义ERR_EXIT("msgget()")打印错误信息,否则继续向下。

    然后使用fopen("./msgsnd.txt", "rb")以只读方式打开目录下的二进制文件alg.9-0-msgsnd.txt,并把指向该文件流的指针赋给fp,如果fp为空指针,说明fopen()失败,文件打开失败,使用宏定义ERR_EXIT("source data file: ./msgsnd.txt fopen()")打印错误信息,否则继续向下。

    接着,声明一个struct msqid_ds类型的消息队列管理结构体变量msqattr,使用msgctl(msqid, IPC_STAT, &msqattr)获取和设置消息队列的属性,这个函数与共享内存的shmctl函数相似,其中参数msqid是队列标识符,参数IPC_STAT表示把后一个参数&msqattr中的数据设置为消息队列的当前关联值,函数的返回值赋给ret。

    然后打印消息队列中存有的信息条数以及消息队列中还剩下的空位数目。

    接着进入一个while循环,检测文件指针fp指向的文件流,如果文件结束,那么结束while循环。进入while循环后,一开始执行fscanf(fp, "%ld %s", &msg_type, buffer);语句,将文件每一行中开头的数字输入进msg_type,后面的姓名字符串输入到buffer,并把fscanf函数的返回值赋给ret,如果ret变量等于EOF,说明文件已经到末尾了,退出while循环,否则继续。

    打印msg_type和buffer中的内容,即文件中每一行的消息类型号和字符串信息,把msg_type赋给struct msg_struct类型变量data的成员变量msg_type,把buffer赋给data的成员变量mtext,使用语句msgsnd(msqid, (void *)&data, TEXT_SIZE, 0)将消息写入消息队列中,其中参数msqid是消息队列的标识符,参数data可以是任何类型的结构体,第一个字段为long类型,表明此发送消息的类型,参数TEXT_SIZE表示要发送的消息的大小,最后一个参数0表示当消息队列满时,函数将会阻塞,直到消息能写进消息队列,并把返回值赋给ret,如果ret为-1,说明msgsnd()失败,使用宏定义ERR_EXIT("msgsnd()")打印错误信息,否则继续向下,统计发送消息总条数的count加一,继续执行while循环。

    从while循环退出后,打印发送消息的总条数,关闭文件指针fp指向的文件流,使用系统命令ipcs -q查看使用消息队列进行进程间通信的信息,最后exit(EXIT_SUCCESS)正常退出。

    执行文件alg.9-2-msgrcv.c

    执行程序命令:

    gcc -o b.out alg.9-2-msgrcv.c
    ./b.out /home/ubuntu/myshm 2
    
    ./b.out /home/ubuntu/myshm 0
    

    实现细节解释:

    首先进入一个条件判断语句,如果argc < 2,那么说明编译命令出错,打印Usage: ./b.out pathname msg_type提示我们补全路径名,以便之后根据文件信息使用ftok()函数获得IPC 键值,并返回EXIT_FAILURE表示异常退出。

    如果编译命令正确,那么继续往下执行,如果获取文件信息失败,进行异常处理,使用宏定义ERR_EXIT("shared file object stat error")打印错误信息,否则继续向下执行。

    接着,通过ftok(pathname, 0x27)获得一个IPC 键值,ftok()函数会根据参数pathname的文件信息和序号参数0x27的计划编号合成IPC key键值并赋给变量key,从而避免用户使用key值时发生冲突。如果key值小于0,说明ftok()失败,使用宏定义ERR_EXIT("ftok()")打印错误信息,否则继续向下执行,打印IPC key = 0x后面跟生成的IPC 键值,显示生成的IPC 键值。

    接下来,使用msgget((key_t)key, 0666)创建一个新的或者打开一个已经存在的消息队列,这个消息队列与key值相对应,并把队列标识符作为返回值赋给变量msqid,其中参数key为IPC键值,后一个参数为0666,而不是(0666 | IPC_CREAT),因为之前已经创建过一个消息队列了,所以不用再创建一个新的消息队列了。

    如果msqid的值为-1,说明msgget()失败,使用宏定义ERR_EXIT("msgget()")打印错误信息,否则继续向下。

    如果argc < 3,那么说明没有指定msgtype变量的值,那么默认该值为0,否则将argv[2]中的值赋给msgtype变量,如果这个值小于0,那么msgtype变量的值赋为0,打印语句Selected message type =msgtype的值,显示msgtype的值。

    接着进入一个while循环,,一开始执行msgrcv(msqid, (void *)&data, TEXT_SIZE, msgtype, IPC_NOWAIT)语句,从消息队列中读取消息,然后把此消息从消息队列中删除,其中参数msqid是消息队列的标识符,参数data是存放消息的结构体,结构体类型要与msgsnd()函数发送的类型相同,参数TEXT_SIZE表示要接收的消息的大小,参数msgtype为0时表示接收第一个消息,大于0表示接收等于msgtype的第一个消息,最后一个参数IPC_NOWAIT表示如果没有返回条件的信息调用立即返回,函数返回值赋给ret,如果ret为-1,说明该种msgtype类型的信息已经读取完了,打印读取的信息数,并退出while循环,否则继续执行。打印读取到的消息的消息类型号和内容,代表读取的信息数量的count变量数值加一,继续while循环。

    退出while循环后,声明一个struct msqid_ds类型的变量msqattr,然后使用msgctl(msqid, IPC_STAT, &msqattr)获取和设置消息队列的属性,把参数&msqattr中的数据设置为消息队列的当前关联值,函数的返回值赋给ret。

    打印此时消息队列中存有的消息条数,如果消息条数等于0,打印语句do you want to delete this msg queue?(y/n),并进入选择判断语句if (getchar() == 'y'),如果接下来输入的字符为'y',那么使用msgctl(msqid, IPC_RMID, 0)语句删除消息队列,如果函数的返回值为-1,说明msgctl()失败,使用perror("msgctl(IPC_RMID)")打印错误信息,否则继续向下。

    使用系统命令ipcs -q打印使用消息队列进行进程间通信的信息,最后exit(EXIT_SUCCESS)正常退出。

    执行截图:

    可以看到,当输入的msgtype值为2时,消息队列中两个msgtype值为2的消息被取出,消息队列中的消息数从8变成6,当输入的msgtype值为0时,因为每次都会不区分类型地将消息队列中的第一条消息取出,所以最后全部消息被取出,消息队列为空,输入’y’删除这个空的消息队列。

    • 修改代码,观察在 msgsnd 和 msgrcv 并发执行情况下消息队列的变化情况。

    实验内容原理:

    首先,进程msgsnd先被执行,使用一个文件路径名和整数标识符通过ftok()获得一个IPC键值,利用这个IPC键值创建一个消息队列,然后使用vfork()和execv()将创建IPC键值时使用的文件路径名传给msgrcv进程,msgrcv进程通过同样的文件路径名和整数表标识符获得同样的IPC键值,通过这个IPC键值获得同一个消息队列。

    此时msgrcv进程和msgsnd进程并发执行,在父进程msgsnd进程中,每休眠2s,向消息队列发送一次消息,在子进程msgrcv进程中,每休眠3s,从消息队列中读取一次消息,消息队列中的消息被一边写一边读,写的速度比读快,不会出现先读完还有消息未写入进程msgrcv就退出的情况。

    当最后消息写完时,msgsnd进程的while循环先退出,消息不再写入,等待msgrcv进程结束,到了消息读完时,msgrcv进程的while循环退出,弹出提示是否删除消息队列的提示,进行完操作后,msgrcv进程结束,然后msgsnd进程结束,程序退出。

    执行程序命令:

    gcc -o msgrcv.o msgrcv.c
    gcc msgsnd.c
    ./a.out /home/ubuntu/myshm
    

    执行截图:

    分析:

    可以看到,当有消息写入消息队列时,消息队列的消息数加一,当有消息从消息队列中读出时,消息队列的消息数减一。

    实验内容2:仿照 alg.8-4~8-6,编制基于 POSIX API 的进程间消息发送和消息接收例程。

    实验内容原理:

    基于 POSIX API 的进程间消息发送和消息接收使用消息队列进行,首先要在程序中包含头文件#include <mqueue.h>,在这个头文件中:

    #include <bits/types.h>
    
    typedef int mqd_t;
    
    struct mq_attr
    {
    __syscall_slong_t mq_flags;	/* Message queue flags.  */
    __syscall_slong_t mq_maxmsg;	/* Maximum number of messages.  */
    __syscall_slong_t mq_msgsize;	/* Maximum message size.  */
    __syscall_slong_t mq_curmsgs;	/* Number of messages currently queued.  */
    __syscall_slong_t __pad[4];
    };
    

    可以看到mqd_t类型实际为int型,消息队列属性mq_attr的结构中,__syscall_slong_t实际上为long型,所有的成员变量都为长整型,mq_flags代表消息队列的标志,0为阻塞模式,O_NONBLOCK为非阻塞模式,mq_maxmsg代表最大消息数,mq_msgsize代表每个消息最大的字节数,mq_curmsgs代表当前的消息数目。

    使用POSIX标准规定的函数在进程操作消息队列,相关的函数有:

    mq_open()用于打开或创建一个消息队列。
    
    mq_getattr()用于获取当前消息队列的属性
    
    mq_send()用于向消息队列中写入一条消息
    
    mq_receive()用于从消息队列中读取一条消息
    
    mq_close()用于关闭一个消息队列
    
    mq_unlink()用于删除一个消息队列
    

    实现细节解释:

    首先在进程msgpthreadcon中使用语句mq_open(pathname, O_CREAT|O_RDWR, 0666, 0)根据文件路径名创建一个可读可写的消息队列,其中参数
    pathname为消息队列的名字,O_CREAT|O_RDWR为打开的方式,这里为可读可写,没有则创建,0666代表默认访问权限为可读可写,0代表采取默认属性。然后创建msgproducer和msgconsumer两个子进程,并发执行,实现通信,同时把创建消息队列时用到的文件路径名传给这两个进程。

    在进程msgproducer中:

    在进程msgproducer中,首先使用语句mq_open(argv[1], O_RDWR, 0666)根据和父进程相同的文件路径名获取同一个消息队列,然后声明一个struct mq_attr的变量mqAttr,用来获取消息队列的属性。

    然后进入一个while循环,在while循环中,每次一开始便使用mq_getattr(mqid, &mqAttr)获取消息队列的属性到mqAttr,如果消息队列中还有消息,那么每次进程休眠1s,等待消息读出后再读入消息,从键盘读入消息到字符型数组buffer后,使用mq_send(mqid, buffer, mqAttr.mq_msgsize, 0)函数将buffer中的内容送到消息队列,其中参数mqid为消息队列的标识符,buffer为要传送的内容,mqAttr.mq_msgsize消息的长度,0为消息的优先级,这里表示不设置优先级。

    如果输入的消息为"end",那么退出循环,使用mq_close(mqid)关闭消息队列,退出进程。

    在进程msgconsumer中:

    首先使用语句mq_open(argv[1], O_RDWR, 0666)根据和父进程相同的文件路径名获取之前创建的消息队列,然后声明一个struct mq_attr的变量mqAttr,用来获取消息队列的属性。

    然后进入一个while循环,在while循环中,每次一开始便使用mq_getattr(mqid, &mqAttr)获取消息队列的属性到mqAttr,如果消息队列中没有消息,那么每次进程休眠1s,等待消息写入后再读出消息,使用mq_receive(mqid, buffer, mqAttr.mq_msgsize, 0)函数将消息队列中的消息读入字符型数组buffer中,其中参数mqid为消息队列的标识符,buffer为要读入的字符型数组,mqAttr.mq_msgsize消息的长度,0为消息的优先级,这里表示不设置优先级。

    如果读出的消息为"end",那么退出循环,使用mq_close(mqid)关闭消息队列,退出进程。

    两个进程都执行完后,回到进程msgpthreadcon重新执行,使用语句mq_unlink(argv[1])删除消息队列,程序退出。

    执行程序命令:

    gcc msgpthreadcon.c -lrt
    gcc -o msgproducer.o msgproducer.c -lrt
    gcc -o msgconsumer.o msgconsumer.c -lrt
    ./a.out /mymsg
    

    执行截图:

    分析:

    可以看到,Producer输入什么,Consumer就输出什么,每次输入的内容和输出的内容一样,实现了Prodecer和Consumer之间的通信,当输入的内容为end时,通信程序结束。

    展开全文
  • 进程间通信总结

    2021-01-21 15:02:40
    概念:一种用于有亲缘关系的两个或多个进程之间的通信手段,可以提供单向的数据流,又称为无名管道。由于管道没有名字,只能用于有共同祖先进程的各个进程之间通信。 特点: (1)半双工通信(即单向数据流),有...
  • 实验要求完成如下任务: 1. 编程实现基于消息缓冲队列机制的进程通信数据结构和 通信原语(创建消息、发送消息、接收消息); 2. 最后编写主函数对所做工作进行测试。
  • 运行进程管理及进程通信(一)中给出的例子,查看自己运行的结果,并进行分析。  程序1 #include "stdio.h" main() { int i,j,k; if (i=fork()) { j=wait(); printf("Parent Process!\n"); printf("i=%d,j=%d,k=%...
  • 《实验二进程通信-Linux实验报告》由会员分享,可在线阅读,更多相关《实验二进程通信-Linux实验报告(9页珍藏版)》请在人人文库网上搜索。1、实验报告学号_____ 姓名____ ___ 成绩 实验二 进程通信 【实验目的和要求...
  • 实验内容:进程间通信—共享内存。 (1)、验证:编译运行课件 Lecture 08 例程代码: Linux 系统调用示例 reader-writer 问题:Algorithms 8-1 ~ 8-3. POSIX API 应用示例 producer-consumer 问题:Algorithms 8-4 ~...
  • Linux软中断通信实验报告实验2 Linux软中断通信1.实验目的通过本实验,掌握软中断的基本原理;掌握中断信号的使用、进程的创建以及系统计时器的使用。2.实验内容(上交的实验2统一取名为:test2由父进程创建两个子...
  • system V 进程间通信 实验报告 姓名: _______罗海员_________ 学号: ____201458506232_______ 班级: ________146-2__________ 实验报告提交时间 _______________ 验收时间 _______________ 评语: − −
  • Linux实验报告

    2021-05-10 08:13:27
    课程编号:B080103040Linux操作系统 实验报告姓 名 班 级 实验名称 邵春晓 软工1201 学 号 指 导 教 师 Linux操作系统实验 20124670 石 凯 开 设 学 期 实 验 时 2014-2015第一学期 第11周——第18周 评定人签字 ...
  • 操作系统实验报告(LINUX进程间通信)

    热门讨论 2008-12-30 21:32:51
    操作系统实验报告(LINUX进程间通信)
  • 5、了解什么是信号,利用信号量机制熟悉进程间软中断通信的基本原理, 6、熟悉消息传送的机理 ,共享存储机制 。 二、 实验环境 Ubuntu 20.10,gcc编译器 三、 实验内容 编写一段程序,使用系统调用fork( )创建两...
  • 操作系统实验四:Linux下进程管道通信 任务1:使用Pipe创建管道,创建一个子进程,子进程向父进程发送消息“I am your son!”,父进程接收到子进程的消息后,显示在屏幕上,并向子进程发送“I am your father!”。子...
  • 东南大学操作系统课程设计实验报告 基于WRK的进程间通信实验
  • 5 基于共享内存的进程间通信-实验1:使用内存映射文件实现进程间通信 一.实验目的 ·使用内存映射文件实现进程通信的方法 ·使用内存映射文件方法加速IO操作的原理 二.实验背景 ·共享内存的基础是内存映射 ·...
  • 苏州大学操作系统原理实验。 实验报告第二个实验。 使用内存共享的方式进行进程间通信,真正的实现通信,而非单个进程的伪通信。 使用MFC的窗口模式实现的。
  • 进程间通信的总结

    2019-01-31 20:10:05
    Linux中使用较多的进程间通信  1.管道(Pipe)及 有名管道:管道可用于具有亲缘关系进程间的通信,对于有名管道,还具有无亲缘关系进程间的通信。  管道是基于文件描述符的通信方式  注意:当一个管道共享多对...
  • 实验内容:进程间通信—管道和 socket 通信。 编译运行课件 Lecture11 例程代码: alg.11-3-socket-input-2.c alg.11-4-socket-connector-BBS-2.c alg.11-5-socket-server-BBS-3.c 实验环境 架构:Intel x86...
  • 操作系统课设之Linux 进程间通信

    千次阅读 2021-06-28 17:29:30
    操作系统课程设计 Linux进程通信 Linux消息通信机制

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,734
精华内容 3,093
关键字:

进程间的通信实验报告

友情链接: num.rar