【42.进程间通信】


进程间通信(IPC)的六种方式:管道、消息队列、共享内存、信号量、信号、网络套接字

管道

管道是UNIX系统IPC的最古老形式。未命名管道只能在相关进程间使用,且要有共同的进程祖先。而命名进程可以在不相关进程间交换数据
未命名管道使用:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/wait.h>
int main(){
    int n;
    int fd[2];//fd[0]read,fd[1]write   
    pid_t pid;
    char line[1024];
    assert(pipe(fd)>=0);
    if((pid=fork())==0){
        close(fd[0]);
        write(fd[1],"this is child\n",15);
        close(fd[1]);
        exit(0);
    }
    else if(pid>0){
        close(fd[1]);
        n=read(fd[0],line,1024);
        printf("%s",line);
        close(fd[0]);
    }
    waitpid(pid,NULL,0);
    return 0;

消息队列

消息队列是消息的链接表,存储在内核中,由消息队列标识符标识。标识符是其内部名,与文件描述符不同,因此不能用文件系统相关函数,需要使用匹配的系统调用,msgsnd添加消息,msgrcv取消息,可以按先进先出顺序,也可以按消息类型取消息。消息队列需要显式删除

共享内存

共享内存允许多个进程共享一个给定的存储区。共享存储段是内存的匿名段,紧靠在栈之下

信号量

信号量是一个计数器,用于限制访问共享资源的数量。
信号量大于0时表示进程可以使用该资源,此时信号量减一;信号量为0,进程休眠,直到信号量大于0,唤醒后访问资源;进程使用完资源后信号量加一
有命名与未命名两种,未命名信号量存在内存中,因此需要能访问同一内存,一般用于同一进程中的线程中

信号

Unix系统提供了许多名字以SIG开头的信号,用于处理异步事件,比如SIGINT信号可以终止程序等。这些信号一般都有默认动作,但也可以编写信号处理函数来表示想要执行的动作

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>

void sig_handler(int sig){
    printf("Caught SIGCHLD!\n");
    exit(0);
}


int main(){
    //sigaction 结构体成员:sa_handler:信号处理函数地址,sa_mask:阻塞信号的集合,sa_flags:处理信号的各种选项
    struct sigaction sa;
    memset(&sa,'\0',sizeof(sa));
    sa.sa_handler=sig_handler;
    sigfillset(&sa.sa_mask);
    //sigaction参数:要捕获的信号,相应sigaction结构体指针(空时默认处理),上一次发生动作相应的sigaction结构体指针保存
    assert(sigaction(SIGCHLD,&sa,NULL)!=-1);
    pid_t pid;
    if((pid=fork())==0){
        exit(0);
    }
    else if(pid>0){
        waitpid(pid,NULL,0);
    }
    return 0;
}

网络套接字

网络套接字用于进程间通信,不仅可以应用于同一主机的进程通信,也可以用于不同主机间的通信

参考
UNIX网络编程 卷1:套接字联网API 第3版

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
31. 在Linux系统下,发送信号的命令是kill。在C语言中,可以使用kill函数来发送信号。 32. pid_t fork() 的返回值为新进程进程ID,如果返回值为0,则表示当前进程为子进程;如果返回值大于0,则表示当前进程为父进程,返回值即为子进程进程ID;如果返回值为-1,则表示创建子进程失败。 33. 系统调用是通过操作系统提供的接口直接调用内核功能的一种编程方式,而库函数则是在用户空中运行的函数库,通过调用库函数来实现对系统功能的访问。 34. C/S架构指的是客户端/服务器架构,其中客户端和服务器通过网络进行通信,客户端向服务器发起请求,服务器处理请求并返回结果给客户端。 35. sprintf函数是C语言中的字符串格式化函数,用于将格式化后的字符串输出到指定的缓冲区中。 36. 进程的创建可以通过fork函数来实现,进程通信的机制包括管道、共享内存、消息队列、信号量等。 37. 线程的创建可以通过pthread_create函数来实现,线程通信的机制包括互斥锁、条件变量、信号量等。 38. 如果a可能为负数,则应该定义为有符号类型。 39. 可以使用wait或waitpid函数来让父进程等待子进程结束并获取子进程的退出状态。 40. 使用管道和共享内存时,需要先创建相应的管道或共享内存,然后通过读写操作来进行进程通信。 41. 进程关闭后,管道或共享内存仍然存在,但是不能再进行读写操作。 42. 僵尸进程是指已经结束但是父进程还没有处理其退出状态的进程。在父进程没有使用wait或waitpid等函数来处理子进程退出状态时,子进程就会变成僵尸进程。 43. 解决僵尸进程的方法包括使用wait或waitpid函数等待子进程退出并获取其退出状态,或者使用信号处理函数来处理SIGCHLD信号。 44. 进程是系统中正在运行的程序的实例,拥有独立的内存空和资源。线程是进程中的执行单元,多个线程共享同一进程的资源,可以提高程序的并发性和效率。 45. 进程通信方式包括管道、共享内存、消息队列、信号量等。 46. 同步是指协调多个进程或线程的执行顺序,保证它们按照一定的顺序执行。互斥是指在同一时只有一个进程或线程可以访问共享资源,其他进程或线程需要等待该进程或线程释放资源后才能访问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值