UC成长之路12

回顾:
UC成长之路1
UC成长之路2
UC成长之路3
UC成长之路4
UC成长之路5
UC成长之路6
UC成长之路7
UC成长之路8
UC成长之路9
UC成长之路10
UC成长之路11

一、进程间通讯

  • system v ipc,IPC(internal process communication),进程间通讯

  • 消息队列

  • 共享内存

  • 信号量集(以后讲)
    注: 下面统称以上三个为这些对象
    在这里插入图片描述

  • 使用ipcs查看这些对象的内容
    在这里插入图片描述

  • 系统要管理这些对象,需要对每一个对象都有一个唯一的编号(id)

    • 消息队列 msqid
    • 共享内存 shmid
    • 信号量集 semid
消息队列
  • 需要在用户空间获取一个键值(具有唯一性),使用这个键值获取一个对象
    • 获取键值:ftok(3)
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
//功能:将pathname和proj_id转换为system v IPC的键值
//参数
//pathname:指定文件路径
//proj_id:指定一个非0值,使用这个值得低有效8位
//返回值:成功返回key_t类型的值;错误返回-1,errno被设置

eg:使用ftok(3)获取一个键值,验证proj_id低8位有效

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>

int main(void)
{
    //key_t key = ftok(".", 1);
    key_t key = ftok(".", 257);
    if(key==-1){
        perror("ftok");
        return -1; 
    }   
    printf("key=%d\n", key);
    return 0;
}

在这里插入图片描述

  • 消息队列:获取消息队列的id,使用msgget(2)
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
 int msgget(key_t key, int msgflg);
 //功能:获取一个消息队列的id
 //参数
 //key:跟消息队列id绑定的键值,即ftok(3)的返回值
 //msgflg:1)IPC_CREAT:消息队列不存在,创建消息队列
 //2)IPC_EXCL:如果和IPC_CREAT一起指定,在消息队列存在的情况下报EEXIST错
 //3)mode:指定了消息队列的权限
 //返回值:成功返回消息队列的id;错误返回-1,errno被设置

eg:使用msgget(2)获取消息队列的id

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int main(void)
{
    //獲取鍵值
    key_t key = ftok(".", 257);
    if(key==-1){
        perror("ftok");
        return -1;
    }
    printf("key=0x%x\n", key);
    //獲取消息隊列
    int msgflg = IPC_CREAT|0644;
    int msgid = msgget(key, msgflg);
    if(msgid==-1){
        perror("msgget");
        return -1;
    }
    printf("msgid=%d\n", msgid);
    return 0;
}

在这里插入图片描述

  • 使用消息队列实现两个进程间的通讯
    • 发送消息到消息队列msgsnd(2)
    • 从消息队列获取消息msgrcv(2)
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//功能:发送消息到消息队列
//参数
//msqid:指定了接受消息队列的id
//msgp:是一个地址,指向struct msgbuf类型变量的地址
//msgsz:指定了结构体中mtext字段的长度
//msgflg:默认为0阻塞;IPC_NOWAIT非阻塞(详细请看下面的注意)
//返回值:成功返回0;错误返回-1,errno被设置
//注意:如果消息队列中有充足的空间接收消息,放入消息队列后立即返回;
//如果消息队列中没有充足的空间接收信息,默认阻塞。可以修改msgflg参数
//中包含IPC_NOWAIT,使得进程步阻塞,立即返回,报错。

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
//功能:从消息队列获取消息
//参数
//msqid:指定了消息队列的id,从这个消息队列获取消息
//msgp:存放消息的缓冲首地址
//msgsz:指定了msgp参数指定的结构体中mtext字段的最大值
//msgtyp:指定了请求消息的类型
//msgflg:IPC_NOWAIT 非阻塞 (还有其它的宏,使用man 2 msgsnd查看)
//返回值:成功返回从消息队列中获取的字节数;错误返回-1,errno被设置

struct msgbuf {
    long mtype;       /* message type, must be > 0 */
    char mtext[1];    /* message data */
};

eg:pa.c创建消息队列,并向消息队列发送一个消息,pb.c获取消息队列id
pa.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

//caller defined
typedef struct msgbuf {
    long mtype;       /* message type, must be > 0 */
    char mtext[128];    /* message data */
}msgbuf_t;

int main(void)
{
    msgbuf_t mb; 
    //獲取鍵值
    key_t key = ftok(".", 257);
    if(key==-1){
        perror("ftok");
        return -1; 
    }   
    printf("key=0x%x\n", key);
    //獲取消息隊列
    int msgflg = IPC_CREAT|0644;
    int msgid = msgget(key, msgflg);
    if(msgid==-1){
        perror("msgget");
        return -1; 
    }   
    printf("msgid=%d\n", msgid);
    //初始化sturct中的成員
    mb.mtype=3;//mtype>0就行
    strcpy(mb.mtext, "this is a test...\n");
    //向消息隊列中發送消息
    int msg = msgsnd(msgid, &mb, strlen(mb.mtext), 0); 
    if(msg==-1){
        perror("msgsnd");
        return -1; 
    }   

    return 0;
}

在这里插入图片描述pb.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

//caller defined
typedef struct msgbuf {
    long mtype;       /* message type, must be > 0 */
    char mtext[128];    /* message data */
}msgbuf_t;

int main(void)
{
    msgbuf_t mb;//存儲獲取到的消息隊列的內容
    //獲取鍵值
    key_t key = ftok(".", 257);
    if(key==-1){
        perror("ftok");
        return -1; 
    }   
    printf("key=0x%x\n", key);
    //獲取消息隊列
    int msgflg = IPC_CREAT|0644;
    int msgid = msgget(key, msgflg);
    if(msgid==-1){
        perror("msgget");
        return -1; 
    }   
    printf("msgid=%d\n", msgid);
    memset(mb.mtext,0,128);//防止不初始化的空间有不确定值
    //從消息隊列中讀取消息
    ssize_t rcv = msgrcv(msgid, &mb, 128, mb.mtype, 0); 
    if(rcv==-1){
        perror("msgrcv");
        return -1; 
    }   
    printf("%s", mb.mtext);

    return 0;
}

在这里插入图片描述

共享内存:
  • 获取共享内存的id,使用shmget(2)
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
//功能:分配一个共享内存段,并获取这个共享内存段的id
//参数
//key:ftok(3)的返回值
//size:指定了共享内存段的大小
//shmflg:1)IPC_CREAT:共享内存段不存在,创建共享内存段。
//2)IPC_EXCL:
//mode:指定了共享内存段的权限
//返回值:成功返回共享内存段的id;错误返回-1,errno被设置
  • shmat(2), shmdt(2)
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
//功能:将共享内存段关联到进程的地址空间
//参数
//shmid;指定了要关联的共享内存端的id
//shmaddr:指定了进程中的关联地址。如果为NULL由内核选择未使用的地址
//shmflg:SHM_RDONLY表明共享内存段只读;为0共享内存段可读可写
//返回值:成功返回关联内存段的地址;错误返回 (void*) -1, errno被设置
int shmdt(const void *shmaddr);
//功能:解除共享内存段和进程的关联
//参数
//shmaddr:指定了共享内存段关联到进程的地址,即shmat(2)的返回值
//返回值:成功返回0,错误返回-1,errno被设置

eg:使用共享内存段实现进程间的通讯
- shma.c创建共享内存段,将共享内存段关联到的地址空间,然后向内存端中写入字符串“hello beijing”
- shmb.c获取共享内存段的id,从共享内存段中读出字符串,并将字符串输出到显示器
shma.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <string.h>
#include <sys/shm.h>

int main(void)
{
    //獲取鍵值
    key_t key = ftok(".", 14);
    if(key==-1){
        perror("ftok");
        return -1; 
    }   
    printf("key=0x%x\n", key);
    //獲取共享內存段的id
    int shmid = shmget(key, 1024, IPC_CREAT|0664);
    if(shmid==-1){
        perror("shmget");
        return -1; 
    }   
    //將共享內存段關聯到進程的地址空間
    void* p = shmat(shmid, NULL, 0); 
    if(p==(void *)-1){
        perror("shmat");
        return -1; 
    }   
    //操作共享內存段
    strcpy(p, "hello beijing");
    getchar();
    //解除共享內存段和進程的關聯
    shmdt(p);

    return 0;
    
}

在这里插入图片描述
shmb.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <string.h>
#include <sys/shm.h>

int main(void)
{
    //獲取鍵值
    key_t key = ftok(".", 14);
    if(key==-1){
        perror("ftok");
        return -1; 
    }   
    printf("key=0x%x\n", key);
    //獲取共享內存段的id
    int shmid = shmget(key, 1024, IPC_CREAT|0664);
    if(shmid==-1){
        perror("shmget");
        return -1; 
    }   
    //將共享內存段關聯到進程的地址空間
    void* p = shmat(shmid, NULL, 0); 
    if(p==(void *)-1){
        perror("shmat");
        return -1; 
    }   
    //從共享內存段獲取數據v,將數據v輸出到顯示器
    printf("%s\n", (char *)p);
    getchar();
    //解除共享內存段和進程的關聯
    shmdt(p);

    return 0;
    
}

在这里插入图片描述

二、网络的基础

  • 服务器端,客户端
    在这里插入图片描述

  • 什么是服务器?通俗的概念:为客户端提供服务的机器,所以服务器就是机器(硬件),提供服务(服务就是软件)。正式的概念:服务器是软件和硬件的结合。

  • 行业标准就是协议

  • 在计算机网络通讯中采用的是TCP/IP协议簇

  • TCP/IP协议簇分为4层或5层(7层是OSI参考模型,根本就没有实现)

  • 4层:应用层,传输层,网络层,链路层

  • 5层:应用层,传输层,网络层,链路层,物理层

  • 物理层:规定的是电气协议,电器的规格和尺寸

  • 链路层:网帧的相关规定

    • 同一个局域网内必须相同
    • 流行的网帧有两种:
      • 以太网卡
      • 令牌环网卡
    • 网帧由头部、数据体、尾部构成
    • 下面以太网帧的格式意义
      • 头部:目的地址(mac地址)、源地址、类型(0800,0806,8035)
  • 以太网帧的格式
    在这里插入图片描述

  • 以太网数据帧的分用过程图
    在这里插入图片描述

  • IP报文格式:IP报文分为两个部分:头部、数据体
    在这里插入图片描述

  • TCP
    在这里插入图片描述

  • UDP
    在这里插入图片描述

要将数据包传递给对方,必须知道对方的MAC地址和目的端口号。知道对方的IP地址,由IP地址获取MAC地址,最后发送给对方。

在这里插入图片描述

在这里插入图片描述

  • 补充

    • 集线器:只是电流的放大和分流,工作在物理层,第一层数据交换
    • 交换机:交换的是网帧,工作在链路层,第二层数据交换
    • 路由器:交换的是IP报文,工作在网络层,第三层数据交换
      在这里插入图片描述
  • 一个ip地址的构成如下:网路号+主机号

    • 网络号找到网段:局域网
    • 主机号中不能使用全0或全1
      • 全0:代表网段地址
      • 全1:代表本局域网的广播地址
  • 给定一个ip地址,需要知道这个ip地址的网络号和主机号,为获取IP地址的网络号,可以通过子网掩码获取网络号
    eg:192.168.1.130/24
    192.16.1.139/255.255.255.0所以网络号是192.16.1.0
    在这里插入图片描述

  • 127.0.0.1环回地址,测试本机的网络设备是否正常。

  • 网络上的每台机器都有两个表:路由表和arp表

  • sudo route查看路由表

  • sudo arp -a查看arp表

  • ping 目标地址测试两台机器是否可以同行

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值