精华内容
下载资源
问答
  • Linux进程通信实验报告
    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。

    更多相关内容
  • 进程通信实验报告

    2012-06-12 20:01:09
    LINUX进程通信实验 君若为我痴情,吾愿为君死身。
  • 操作系统的第二次作业进程和进程通信,里面截图中的姓名与学号自己PS改一下吧
  • 进程通信实验报告进程通信实验报告进程通信实验报告进程通信实验报告进程通信实验报告进程通信实验报告
  • 编写一段程序,实现进程的管道通信。 使用系统调用pipe( )建立一条管道,创建两个子进程P1和P2。让P1和P2分别向管道各写一句话: child process P1 is sending messages! child process P2 is sending messages! 父...
  • 进程之间通讯实验报告,包含 1.(1)进程的创建 2.(2)进程控制 3.(3)进程间信号通信 4.(4)进程的管道通信 编写程序,创建两个子进程。当此程序运行时,系统中有一个父进程和两个子进程。父进程在屏幕上显示...
  • 实验2 Linux软中断通信 1.实验目的 通过本实验掌握软中断的基本原理掌握中断信号的使用进程的创建以及系统计时器的使用 2.实验内容上交的实验2统一取名为test2) 由父进程创建两个子进程通过终端输入Crtl+\组合键向父...
  • 实验六Linux进程间通信24课时 实验目的 理解进程通信原理掌握进程中信号量共享内存消息队列相关的函数的使用 实验原理 Linux下进程通信相关函数除上次实验所用的几个还有 信号量 信号量又称为信号灯它是用来协调不同...
  • 运行进程管理及进程通信(一)中给出的例子,查看自己运行的结果,并进行分析。  程序1 #include "stdio.h" main() { int i,j,k; if (i=fork()) { j=wait(); printf("Parent Process!\n"); printf("i=%d,j=%d,k=%...
  • 进程控制与通信实验报告书(09版)进程控制与通信实验报告书(09版)进程控制与通信实验报告书(09版)
  • 实验报告详细描述了进程通信的实现原理,使用管道以及信号实现进出那个间通信,附有源代码实现。
  • 5、了解什么是信号,利用信号量机制熟悉进程间软中断通信的基本原理, 6、熟悉消息传送的机理 ,共享存储机制 。 二、 实验环境 Ubuntu 20.10,gcc编译器 三、 实验内容 编写一段程序,使用系统调用fork( )创建两...

    在这里插入图片描述

    一、 实验目的

    1、掌握进程的概念,明确进程的含义。
    2、认识并了解进程并发执行的实质,进程的阻塞与唤醒,终止与退出的过程。
    3、熟悉进程的睡眠、同步、撤消等进程控制方法。
    4、分析进程竞争资源的现象,学习解决进程互斥的方法 。
    5、了解什么是信号,利用信号量机制熟悉进程间软中断通信的基本原理,
    6、熟悉消息传送的机理 ,共享存储机制 。

    二、 实验环境

    Ubuntu 20.10,gcc编译器

    三、 实验内容

    1. 编写一段程序,使用系统调用fork( )创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程并发执行,观察实验结果并分析原因。

    2. 用fork( )创建一个进程,再调用exec( ),用新的程序替换该子进程的内容,利用wait( )来控制进程执行顺序,掌握进程的睡眠、同步、撤消等进程控制方法,并根据实验结果分析原因。

    3. 编写一段多进程并发运行的程序,用lockf( )来给每一个进程加锁,以实现进程之间的互斥,观察并分析出现的现象及原因。

    4. 编写程序:用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按^c键);捕捉到中断信号后,父进程用系统调用kill( )向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:
      Child process1 is killed by parent!
      Child process2 is killed by parent!
      父进程等待两个子进程终止后,输出如下的信息后终止:
      Parent process is killed!
      分析利用信号量机制中的软中断通信实现进程同步的机理。

    5. 使用系统调用msgget( ),msgsnd( ),msgrev( ),及msgctl( )编制一长度为1k的消息发送和接收的程序,并分析消息的创建、发送和接收机制及控制原理。

    6. 编制一长度为1k的共享存储区发送和接收的程序,并设计对该共享存储区进行互斥访问及进程同步的措施,必须保证实现正确的通信。

    四、 实验原理 实验中用到的系统调用函数(包括实验原理中介绍的和自己采用的),实验步骤

    实验原理:

    实验步骤:

    第一题:

    因为题目说创建2个子进程,而根据fork()函数的返回值可以发现,如果返回值==0表示当前是子进程,返回值>0说明当前是父进程,根据这一点就可以通过if-else语句将程序分开成两个不同的进程运行!
    在这里插入图片描述

    第二题:

    一开始采用跟第一题一样的创建进程的方法,只是在子进程中调用 execl()从而替代了后面的内容:
    在这里插入图片描述
    同时也在父进程中调用wait(),保证父进程不会提前结束:
    在这里插入图片描述

    第三题:

    先创建2个子进程,然后在2个子进程里面都先加锁,通过for循环输出10个数字,执行结束之后再解锁:
    在这里插入图片描述

    第四题:

    先创建2个子进程,然后在进程里面接收信号,后面需要用pause()函数来使程序暂停,直到接收到信号。接收到终止信号之后再向子进程发出信号。
    在这里插入图片描述
    子进程接收到信号后,终止程序的运行。
    在这里插入图片描述
    父进程最后调用wait()保证了父进程在最后结束。
    在这里插入图片描述

    第五题:

    首先在main函数中创建2个进程:
    父进程中调用server(),接收消息。
    子进程中调用client(),发送消息。
    在这里插入图片描述
    client()函数中发送消息:
    在这里插入图片描述
    server()函数中发送消息:
    先调用wait()函数等client发送完消息并结束进程再接收消息。
    在这里插入图片描述

    第六题:

    main()函数中创建1个子进程执行server,父进程执行client
    在这里插入图片描述
    client中发送消息
    在这里插入图片描述
    server中接收消息:
    在这里插入图片描述
    server一接收到消息都会把addr置为-1,以等待client再次发送消息。

    五、 实验结果分析(截屏的实验结果,与实验结果对应的实验分析)

    1、实验结果与实验程序、实验步骤、实验原理、操作系统原理的对应分析;
    2、不同条件下的实验结果反应的问题及原因;
    3、实验结果的算法时间、效率、鲁棒性等性能分析。

    第一题:

    在这里插入图片描述

    在CPU多核的情况下,通过实验结果可以发现,多次执行程序,“父进程”“子进程1”“子进程2”输出的顺序都不一样。说明3个进程的执行顺序都是不确定的,这取决于进程的调度时机。
    然后把CPU调到1核,重启,
    在这里插入图片描述
    在这里插入图片描述
    可以发现在单核的情况下,执行顺序相对固定,都是先执行的父进程再执行2个子进程。因为单核CPU在处理多线程程序时只能执行一跳指令,每个进程都是轮流执行,所以单核CPU在一定程度上控制了实验结果的随机性。

    第二题:

    在这里插入图片描述
    执行程序,可以发现程序把当前文件夹下的所有文件都输出了。

    第三题:

    在这里插入图片描述
    可以发现,每个进程加锁之后,都不会切换到另外2个进程去执行,只有该进程执行完毕之后解锁之后,才会切换到下一个进程去执行。

    第四题:

    正在运行程序:
    在这里插入图片描述
    开启一个新的终端,执行kill -2 54969,向父进程发送中断信号:
    在这里插入图片描述
    最终的运行结果如下:
    在这里插入图片描述

    第五题:
    server中已成功接收到cilent发送的信息并显示出来。
    在这里插入图片描述

    第六题:
    client每发送一条消息,server都会接收之后,client才会发送下一条消息。
    在这里插入图片描述

    六、实验总结

    每一道题都是自己先在网上找了一些资料之后才开始的,花费了比较长的时间,也遇到了许多困难,比如在linux系统中操作,遇到了许多不适应的地方,很多不懂的地方也是自己花了很多时间搜索资料解决的。但是收获也很大,通过本次的实验,我也对进程、消息和共享区有了更进一步的了解。

    七、实验数据及源代码(学生必须提交自己设计的程序源代码,并有注释,源代码电子版也一并提交),包括思考题的程序。

    第一题

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    
    int main()
    {
    	int p;
    	p = fork();
    	if (p < 0)
    	{
    		//fork()函数的返回值<0表示进程创建失败!
    		printf("子进程创建失败!\n");
    	}
    	else if (p == 0)
    	{
    		//p==0表示这是子进程
    		printf("我是第一个子进程,号码是%d\n", getpid());
    		exit(0); //中断进程
    	}
    	else
    	{
    		//p>0表示当前是父进程
    		//创建第二个子进程
    		int q;
    		q = fork();
    		if (q < 0)
    		{
    			printf("子进程创建失败!\n");
    		}
    		else if (q == 0)
    		{
    			printf("我是第二个子进程,号码是%d\n", getpid());
    			exit(0);
    		}
    		else
    		{
    			printf("我是父进程,号码是%d\n", getpid());
    			exit(0); //中断进程
    		}
    	}
    }
    
    

    第二题

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    int main()
    {
    	int p;
    	p = fork(); //创建子进程
    	switch (p)
    	{
    	case -1:
    		printf("创建失败\n");
    		exit(1);
    	case 0: //子进程
    		execl("/bin/ls", "ls", NULL);
    		printf("execfail!\n");
    		exit(1);
    	default:		//父进程
    		wait(NULL); //先暂停父进程,避免父进程提前结束!
    		printf("lscompleted!\n");
    		exit(0);
    	}
    }
    
    

    第三题

    #include <stdio.h>
    #include <unistd.h>
    int main()
    {
        int p;
        int i;
        p = fork(); //创建子进程
        if(p < 0){
            printf("第一个子进程创建失败\n");
        }else if(p == 0){
            //当前是子进程
            lockf(1,1,0);   //加锁
            for(i = 0;i <10;++i){
                printf("%d\n",i);
            }
            printf("第一个子进程执行完成\n");
            lockf(1,0,0);   //解锁
        }else{
            p = fork();  //创建第二个子进程
            if(p < 0){
                printf("第二个子进程创建失败\n");
            }else if(p == 0){
                //子进程
                lockf(1,1,0);   //加锁
                for(i = 10;i <20;++i){
                    printf("%d\n",i);
                }
                printf("第二个子进程执行完成\n");
                lockf(1,0,0);   //解锁
            }else{
                //当前是父进程
                lockf(1,1,0);   //加锁
                for(i = 20;i <30;++i){
                    printf("%d\n",i);
                }
                printf("父进程执行完成\n");
                lockf(1,0,0);   //解锁
            }
        }
    }
    
    

    第四题

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <signal.h>
    #include<sys/wait.h>
    
    void sighandler(int sig){
        //printf("Response\n");
    }
    
    int main(){
    
        int pid1;
        int pid2;
        pid1 = fork(); //创建第一个子进程
        if(pid1 == 0){
            //第一个子进程
            printf("我是第一个子进程,pid=%d\n",getpid());
            signal(SIGUSR1,sighandler);   //接受信号
            pause();   //程序暂停,直到信号出现
            printf("Child process1 is killed by parent!\n");  
            exit(1);
        }else{
            pid2 = fork(); //创建第二个子进程
            if(pid2 == 0){
                // 第二个子进程
                printf("我是第二个子进程,pid=%d\n",getpid());
                signal(SIGUSR2,sighandler);   //接受信号
                pause();   //程序暂停,直到信号出现
                printf("Child process2 is killed by parent!\n");
                exit(2);
            }else{
                //父进程
                printf("我是父进程,pid=%d\n",getpid());
                signal(SIGINT,sighandler);
                pause();
                kill(pid1,SIGUSR1); //向进程pid1发送用户自定义信号1
                kill(pid2,SIGUSR2); //向进程pid2发送用户自定义信号2
                wait(NULL);
                wait(NULL);
                wait(NULL);         //等待两个子进程
                printf("Parent process is killed!\n");
                exit(0);
            }
        }
    }
    
    

    第五题

    #include<sys/types.h>
    #include<sys/ipc.h>
    #include<sys/msg.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include<string.h>
    #include<sys/wait.h>
    
    #define MSGKEY 1024  //消息key
    
    typedef struct msgForm{ //消息结构体
        long  mtype;            /*消息类型*/
        char  mtext[1024];      /*消息的文本*/
    }msgForm;
    
    int msgqid;
    
    void client(){
        msgForm msg;
        msg.mtype = 10; //定义消息类型
        strcpy(msg.mtext,"Hello,World!!!");
        msgqid = msgget(MSGKEY,0777); //创建消息队列
        msgsnd(msgqid,&msg,sizeof(msg),0);
        printf("(client)已发送信息!\n");
        printf("(client)发送的信息为%s\n",msg.mtext);
        exit(0);
    }
    
    void server(){
        msgForm msg;
        msgqid=msgget(MSGKEY,0777|IPC_CREAT); //创建一个所有用户都可以读、写、执行的队列
        wait(0);    //保证cilent发送完消息并结束进程之后才继续执行下面
        msgrcv(msgqid,&msg,sizeof(msg),0,0);    //接受信息
        printf("(server)已接受信息!\n");
        printf("(server)接受到的信息为%s\n",msg.mtext);
        msgctl(msgqid, IPC_RMID,0); //消除消息队列的标识符。
        exit(0);
    }
    
    
    int main(){
        int p;
        p = fork(); //创建子进程
        if(p == 0){
            client();
        }else{
            server();
        }
        return 0;
    }
    

    第六题

    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/wait.h>
    
    #define SHMKEY 1024 // 共享存储区的key
    int shmid, i;
    int *addr;
    
    void client()
    {
        int i;
        shmid = shmget(SHMKEY, 1024, 0777 | IPC_CREAT); /*创建一个共享存储区,名字为75,大小为1024字节,不重复创建*/
        addr = shmat(shmid, 0, 0);                      /*共享存储区所附接到的进程虚地址(首地址)*/
        for (i = 9; i >= 0; i--)
        {
            while (*addr != -1); //确保服务端收到了一条信息,再发下一条
            printf("(client)sent\n");
            *addr = i;
        }
        exit(0);
    }
    
    void server()
    {
        shmid = shmget(SHMKEY, 1024, 0777 | IPC_CREAT); //创建一个共享存储区,大小为1024字节
        addr = shmat(shmid, 0, 0);                      //共享存储区所附接到的进程虚地址(首地址)
        do
        {
            *addr = -1;
            while (*addr == -1);//响应客户端
            printf("(server)received\n");
        } while (*addr);
        shmctl(shmid, IPC_RMID, 0); //撤消共享存储区,归还资源
        exit(0);
    }
    
    void main()
    {
        int p;
        p = fork(); //创建子进程
        if(p < 0){
            printf("子进程创建失败!\n");
        }
        else if(p == 0){
            server();
        }else{
            client();
        }
    
    }
    
    

    八、思考题

    1、进程创建与进程并发执行

    (1)系统是怎样创建进程的?
    答:通过fork()系统调用之后,执行以下操作:
    ① 申请空白PCB(过程控制块)。
    ② 为新工序分配资源。
    ③ 初始化PCB。
    ④ 将新进程插入就绪队列。

    (2)当首次调用新创建进程时,其入口在哪里?
    答:进程的进程控制块(PCB)结构中有指向其TTS(任务状态段)的指针,TTS里面存放着进程的入口。

    (3)利用strace 和ltrace -f -i -S ./executable-file-name查看程序执行过程,并分析原因,画出进程家族树。
    在这里插入图片描述 在这里插入图片描述
    执行过程如图所示,父进程先创建的子进程2再创建子进程1,并且在输出内容后被杀死。进程家族树如图所示:
    在这里插入图片描述

    2、进程的睡眠、同步、撤消等进程控制

    (1)可执行文件加载时进行了哪些处理?
    答:进程用exec( )装入命令ls ,exec( )后,子进程的代码被ls的代码取代,这时子进程的PC指向ls的第1条语句,开始执行ls的命令代码。

    (2)什么是进程同步?wait( )是如何实现进程同步的?
    答:进程同步是指:在多道程序环境下,进程是并发执行的,不同进程之间存在着不同的相互制约关系。wait()函数一调用,父进程就会先暂停执行,直到有一个进程结束之后才去控制。

    (3)wait( )和exit()是如何控制实验结果的随机性的?
    答:子进程在使用了execl()函数之后,列出了当前目录下所有的文件,执行完这个函数之后才去调用exit(),退出当前进程,才去接着继续执行父进程,所以我们可以发现父进程的lscompleted!永远在最后才输出,这样子就控制了实验结果的随机性。

    3、多进程通过加锁互斥并发运行

    (1)进程加锁和未上锁的输出结果相同吗? 为什么?
    答:不相同。因为进程加锁之后,就保证了在执行其中一个进程的时候,不会切换到另外2个进程去执行,只有解锁之后才会切换到另外2个进程。如果进程未上锁,那么程序就会随时切换到另外2个进程执行,输出结果会不相同。

    4、进程间通过信号机制实现软中断通信

    (1)为了得到实验内容要求的结果,需要用到哪些系统调用函数来实现及进程间的通信控制和同步?
    答:kill()和signal()

    (2)kill( )和signal( )函数在信号通信中的作用是什么?如果分别注释掉它们,结果会如何?
    答:

    • kill()函数的作用是向指定的子进程发送信号,signal()的作用是接收指定的信号,signal()后面需要配合pause()函数一起使用。
    • 如果注释掉kill(),那么子进程将接收不到信号,导致子进程一直在等待信号的出现,父进程也一直在等待子进程结束,最终程序一直阻塞。
    • 如果注释掉signal(),那么父进程也接收不到中断信号,发出中断信号后程序也没反应,程序也是一直阻塞。

    5、消息的发送与接收

    (1)为了便于操作和观察结果,需要编制几个程序分别用于消息的发送与接收?
    答:两个程序,其中client发送消息,server接收消息。

    (2)这些程序如何进行编辑、编译和执行?为什么?
    答:
    ① 两个程序分别编辑,执行gcc client.c -o client和gcc server.c -o server
    ② 执行: ./server和 ./client
    ③ client和server是两种不同的程序,需要分开来编辑、编译和执行,client发送请求,server用于接收消息。

    (3)如何实现消息的发送与接收的同步?
    答:发送程序和接收程序都必须一直做好相互通信的准备。

    6、进程的共享存储区通信

    (1)为了便于操作和观察结果,需要如何合理设计程序来实现子进程间的共享存储区通信?
    答:每个进程都需要开辟一个共享存储区,然后附加到自己的一个内存空间中,就可以正常地进行读写操作了。

    (2)比较消息通信和共享存储区通信这两种进程通信机制的性能和优缺点。
    答:
    ①消息队列的建立比共享区的设立消耗的资源少。前者只是一个软件上设定的问题,后者需要对硬件的操作,实现内存的映像,当然控制起来比前者复杂。如果每次都重新进行队列或共享的建立,共享区的设立没有什么优势。
    ②当消息队列和共享区建立好后,共享区的数据传输,受到了系统硬件的支持,不耗费多余的资源;而消息传递,由软件进行控制和实现,需要消耗一定的cpu的资源。从这个意义上讲,共享区更适合频繁和大量的数据传输。
    ③消息的传递,自身就带有同步的控制。当等到消息的时候,进程进入睡眠状态,不再消耗cpu资源。而共享队列如果不借助其他机制进行同步,接收数据的一方必须进行不断的查询,白白浪费了大量的cpu资源。可见,消息方式的使用更加灵活。

    展开全文
  • Linux——进程通信 一、实验目的 (1) 熟悉并掌握管道机制,并实现进程间通信 (2) 熟悉并掌握共享内存机制,并实现进程间通信 二、实验内容 任务一: (1)阅读以上父子进程利用管道进行通信的例子(例1),写...

    理论知识

    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)的区别

     

    展开全文
  • 实验六Linux 进程间通信2 4 课时 实验目的 理解进程通信原理掌握进程中信号量共享内存消息队列相关的函数的使用 实验原理 Linux 下进程通信相关函数除上次实验所用的几个还有 信号量 信号量又称为信号灯它是用来协调...
  • 福州大学Linux 操作系统设计实践报告进程通信,进程间通信之命名管道,进程间的通信之消息队列
  • 程的创建实验、进程的控制实验、进程互斥实验、守护进程实验、 信号机制实验、进程的管道通信实验、消息的发送与接收实验、 共享存储区通信
  • 运行进程管理及进程通信(一)中给出的例子,查看自己运行的结果,并进行分析。 2、编写程序 (1)、要求程序运行时,系统中存在如下图(一)的进程树结构,写出程序源代码及程序运行结果并在进程树的相应进程节点上标...
  • Linux实验报告

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

    课程编号:B080103040

    Linux操作系统 实验报告

    姓 名 班 级 实验名称 邵春晓 软工1201 学 号 指 导 教 师 Linux操作系统实验 20124670 石 凯 开 设 学 期 实 验 时 间 2014-2015第一学期 第11周——第18周 评定人签字 评 定 日 期 石 凯 评 定 成 绩 东北大学软件学院

    实验一 熟悉Linux环境

    【实验内容】

    一、练习常用的Shell命令。

    当用户登录到字符界面系统或使用终端模拟窗口时,就是在和称为shell的命令解释程序进行通信。当用户在键盘上输入一条命令时,shell程序将对命令进行解释并完成相应的动作。这种动作可能是执行用户的应用程序,或者是调用一个编辑器、GNU/Linux实用程序或其他标准程序,或者是一条错误信息,告诉用户输入了错误的命令。 二、熟悉vim编辑器

    在编写文本或计算机程序时,需要创建文件、插入新行、重新排列行、修改内容等,计算机文本编辑器就是用来完成这些工作的。

    Vim编辑器的两种操作模式是命令模式和输入模式(如图2所示)。当vim处于命令模式时,可以输入vim命令。例如,可以删除文本并从vim中退出。在输入模式下,vim将把用户所输入的任何内容都当作文本信息,并将它们显示在屏幕上。 三、熟悉gcc编译器

    GNU/Linux中通常使用的C编译器是GNU gcc。编译器把源程序编译生成目标代码的任务分为以下4步:

    a. 预处理,把预处理命令扫描处理完毕 ;

    b. 编译,把预处理后的结果编译成汇编或者目标模块;

    c. 汇编,把编译出来的结果汇编成具体CPU上的目标代码模块; d. 连接,把多个目标代码模块连接生成一个大的目标模块; 四、熟悉gdb调试工具

    LINUX包含了一个叫gdb的GNU调试程序。gdb是一个用来调试C和C++程序的强有力调试器。它使你能在程序运行时观察程序的内部结构和内存的使用情况。它具有以下一些功能: ·监视程序中变量的值;

    ·设置断点以使程序在指定的代码行上停止执行; ·一行行的执行代码。

    五、掌握Linux下C程序编辑运行过程 Linux下编写C程序要经过以下几个步骤: ⑴启动常用的编辑器,键入C源程序代码。 ⑵编译源程序 ⑶运行可执行文件

    【实验总结】

    在学习linux的过程中间,最主要的就是耐心和细心。linux的命令很多,只有一遍一遍的看一次又一次的用,才能记住很多的命令,才能很好的使用linux。通过这次实验,我对linux的系统以及vim编辑器,gcc编译器,gdb调试工具更加熟悉,这也让我让我能够更加努力学习。

    实验二 文件操作

    【实验内容】

    1.文件的创建(必做题)

    编写程序,实现cp命令的功能。被复制的文件名与复制出的新文件由用户指定。调用方法:“你编写的程序名 被复制文件名 复制出的文件名”。要求程序有一定的健壮性,即对用户错误调用及其他错误要有处理和反馈。(提示:可以使用man手册查看具体的系统调用,e.g., man 2 open)。 #include #include #include #include #include

    main(int ac, char *av[]){ int fd1, fd2; int n;

    char buf[512];

    if(ac!=3){

    printf(\ exit(1); }

    if((fd1=open(av[1], O_RDONLY))==-1){ perror(\ exit(1); }

    if((fd2=creat(av[2], 0777))==-1){ perror(\ exit(1); }

    while((n=read(fd1, buf, 512))>0){ write(fd2, buf, n); }

    close(fd1); close(fd2); }

    展开全文
  • 实验四:进程通信(二) 实验目的: 学习如何利用消息缓冲队列进行进程间的通信,并加深对消息缓冲队列通信机制的理解。 实验内容: (1) 了解系统调用msgget()、msgsnd()、msgrcv()、msgctl()的功能和实现过程。 (2) ...
  • 操作系统实验四:Linux下进程管道通信 任务1:使用Pipe创建管道,创建一个子进程,子进程向父进程发送消息“I am your son!”,父进程接收到子进程的消息后,显示在屏幕上,并向子进程发送“I am your father!”。子...
  • 实验二进程通信-Linux实验报告.docx实验报告学号_ 姓名 _ 成绩 实验二 进程通信 【实验目的和要求】1、了解进程通信的概念及方法;2、了解信号量、管道;3、掌握信号量、管道和命名管道编程方法。【实验内容】1、...
  • 操作系统实验报告8 实验内容 实验内容1:进程通信—消息机制 编译运行课件 Lecture 09 例程代码: Algorithms 9-1 ~ 9-2. 修改代码,观察在 msgsnd 和 msgrcv 并发执行情况下消息队列的变化情况。 ...
  • 实验要求完成如下任务: 1. 编程实现基于消息缓冲队列机制的进程通信数据结构和 通信原语(创建消息、发送消息、接收消息); 2. 最后编写主函数对所做工作进行测试。
  • 操作系统课程实验报告 实习题目 进程间基于消息队列的通信 指导教 学生姓名 学 号 日 期 实现工具 C 语言 实现环境 Linux 系统 实验目的 系统了解linux 系统的通信机构IPC 掌握IPC 中消息通信机 制理解消息通信的...
  • 这是一份关于进程通信实验报告的源代码文件
  • system V 进程通信 实验报告 姓名: _______罗海员_________ 学号: ____201458506232_______ 班级: ________146-2__________ 实验报告提交时间 _______________ 验收时间 _______________ 评语: − −
  • (1) 阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析。 (2) 编写程序:父进程利用管道将一字符串交给子进程处理。子进程读字符串,将里面的字符反向后再交给父进程,父进程最后读取并打印...
  • 操作系统实验报告6 实验内容 实验内容:进程通信—共享内存。 (1)、验证:编译运行课件 Lecture 08 例程代码: Linux 系统调用示例 reader-writer 问题:Algorithms 8-1 ~ 8-3. POSIX API 应用示例 producer-...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,001
精华内容 4,800
关键字:

进程通信实验报告