Linux-操作系统

实验三 进程的通信

&符号

Linux 终端命令的末尾加上一个 & 符号表示将这个任务放到后台去执行

PS命令

ps -c显示进程的实际名称

kill

调用格式:kill(pid,sig)

说明:pid表示一个或一组进程标示符,pid值的定义如下:

 >0:将信号发送给指定的进程

 =0:将信号发送给同组的所有进程

=-1:将信号发送给所有满足如下条件的进程:进程的用户标示符等于发送信号进程的有效用户标示符

Sig为软中断信号(序号或名称)

wait()

当进程调用 wait() 时,wait()会暂停目前进程的执行(即阻塞),由 wait() 来自动分析是否当前进程的某个子进程已经退出,如果找到了这样一个已经变成僵尸进程的子进程,wait 就会收集这个子进程的信息,并将其彻底销毁后返回;如果没有找到这样一个子进程,wait 就会一直阻塞在这里,直到出现僵尸进程。

signal()

signal()函数对捕捉到的信号进行处理,其中函数的第一个参数表示捕捉到的信号,第二个参数函数指针SIG_DFL,它表示默认信号处理程序,如果是SIG_IGN,则表示忽略信号的处理程序。当用户按下第一个Ctrl+C 组合键时,将调用int_func函数,此时信号处理动作将恢复为默认动作,当程序接收到第二个SIGINT信号时,程序采取默认动作,结束运行。

pid=fork()

负值:创建子进程失败。

:说明是新创建的子进程。

正值:说明是父进程,并且该值就是新创建的子进程的进程ID 

信号号码 9  SIGKILL 含义是用来立即结束程序的运行. 本信号不能被阻塞、处理和忽略。如果管理员发现某个进程终止不了,可尝试发送这个信号。

信号号码 18  SIGCONT,含义是让一个停止(stopped)的进程继续执行. 本信号不能被阻塞. 可以用一个handler来让程序在由stopped状态变为继续执行时完成特定的工作. 例如, 重新显示提示符

信号号码 19  SIGSTOP,含义是停止(stopped)进程的执行. 注意它和terminate以及interrupt的区别:该进程还未结束, 只是暂停执行. 本信号不能被阻塞, 处理或忽略.

信号号码 12  SIGUSR2,是用户自定义信号。

代码解释

#include<signal.h>
int k1;
void myfunction()
{
        k1=0;
        printf("child got a signal from father!\n");
}
main()
{
        int k,p1;
        while((p1=fork())==-1);
        if(p1>0)
        {
                for(k=1;k<3;k++)
                {
                        printf("i am father!\n");
                        sleep(1);
                }
                kill(p1,12);
                wait(0);
                printf("my child have exited and I am father !\n");
                exit(0);
        }
        else
        {
                signal(12,myfunction); 
                k1=1;
                while(k1==1)
                {
                        printf("I am a child\n");
                        sleep(1);
                }
                printf("Child exited!\n");
                exit(0);
        }
}
  • 整个程序的执行次序如下
  • 首先p1=fork()创建了父进程和子进程
  • 两个进程依次进入线程队列
  • 首先是父进程的执行
  • 执行for循环时打印father,然后休眠1s
  • 这里的sleep函数代表挂起父进程这时候让子进程进入运行
  • 于是便有while循环里的子进程运行打印child,然后休眠挂起子进程
  • 继续运行父进程 此时k=2
  • 重复上述内容后,我们来到kill(p1,12)这个命令
  • 软中断 将该12信号发送给p1,子进程于是接收到信号
  • 接着wait()挂起父进程,运行子进程直到子进程的结束
  • signal接收到信号于是运行myfunction这个函数
  • 此时可以跳过while循环输出后面的内容了
  • 退出子进程 完成父进程的运行

通道的基本使用

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#define MAX_LINE 80
  int main(){
    int thePipe[2], ret;
    char buf[MAX_LINE+1];
    const char *testbuf="a test string.";
    if ( pipe( thePipe ) == 0 ) {
     if (fork() == 0) {
      ret = read( thePipe[0], buf, MAX_LINE );
      buf[ret] = 0;
      printf( "Child read %s\n", buf );
     } else {
      ret = write( thePipe[1], testbuf, strlen(testbuf) );
      ret = wait( NULL );
     }
   }
close(thePipe[0] );
close(thePipe[1] );
    return 0;
}
  • 无名通道Pipe可以实现父子进程之间的信息流动 

无名管道

无名管道(也称为匿名管道)的创建

系统调用:int  pipe(int PipeName[2]);

参数说明:

PipeName[2],管道名,为一2元整型数组

PipeName[0]专用于读进程

PipeName[1]专用于写进程

返回值:整型。0代表管道创建正确;-1代表管道创建失败。

该管道由创建进程及其子孙进程共享

使用头文件:unistd.h

  • 管道小程序

  • 编写程序pipeuse.c,涉及到4个进程和3个管道,需要完成如下功能:

    P1:从键盘接受字符串,写入管道pipe1。

    P2:从pipe1接受字符串,若字符串的长度为小于10,将其写入管道pipe 2,否则写入管道pipe3

    P3:从pipe2读出字符串,并且显示”I am p3,  I read from pipe2, this is short string.”

    P4:从pipe3读出字符串,并且显示” I am p4,  I read from pipe3, this is long string."

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#define MAX_LINE 80
int main()
{
    int thePipe[2], ret;
    char buf[MAX_LINE + 1];
    const char *testbuf = "a test string.";
    int pid = 0;
    if (pipe(thePipe) == 0)
    {
        printf("s1 %d\n", pid);

        if ((pid = fork()) == 0)
        {
            printf("s2 %d\n", pid);

            ret = read(thePipe[0], buf, MAX_LINE);
            buf[ret] = 0;
            printf("Child read %s\n", buf);
        }
        else
        {

            ret = write(thePipe[1], testbuf, strlen(testbuf));
            close(thePipe[0]);
            close(thePipe[1]);
            printf("s3 %d\n", pid);
        }
        printf("s4 %d\n", pid);
    }
    printf("s5 %d\n", pid);

    return 0;
}
  • 本次实验通过打印调试,得出了如下关于父子进程调度的结论
  • 首先父子进程的调度是由操作系统支配并且是异步的
  • 可以是父子进程交叉打印的结果
  • 其次 使用wait(0)函数可以使父进程在wait后的内容等待子进程运行结束后再运行

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值