{C++系列} UNIX高级编程 day12 system V IPC ,网络基础
in C/C++ with 0 comment

{C++系列} UNIX高级编程 day12 system V IPC ,网络基础

in C/C++ with 0 comment

复习

一,信号的阻塞,未决信号,pause(2)的使用

Subset_t        信号集类型
Subset_t
Typedef int num[128]    num_t

二,信号的生命周期
三,可重入函数
四,作业(前台作业和后台作业)
五,使用setitimer(2)实现定时器

一,system V ipc

以下三种方式每一种方式都是内核中的一类对象。

在内核中每个对象都有自己的id
查看系统中的这些对象

要获取这三种对象必须使用键值。、ftock(2)
键值:键值是一个唯一的值,使用这个唯一的值获取一个对象。

消息队列

如何获取一个消息队列的对象的id

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
Int msgget(key_t key, int msgflg);

功能:获取一个消息队列的返回值
参数
Msgflg:
IPC_CREAT:如果消息队列不存在,就创建一个新的消息队列
O_CREAT|O_EXCL:同open(2)一样
mode:指定了消息队列对象的访问权限
返回值
如果没有和key相关 的消息队列的对象,并且在msgflg中指定了IPC_CREAT。那么就创建一个新的消息队列的对象,并且将这个对象的id返回。
-1 错误 errno被设置
成功 非负值 消息队列的id

举例

获取一个消息队列的对象

 1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/ipc.h>
  4 #include<sys/msg.h>
  5 int main(){
  6         key_t key;
  7         key=ftok(".",51);
  8         if(key==-1){
  9                 perror("ftok");
 10                 return -1;
 11         }
 12         printf("key:0x%x\n",key);
 13         //使用键值获取消息队列
 14         int msqid=msgget(key,IPC_CREAT|0664);
 15         if(msqid==-1){
 16                 perror("msgget");
 17                 return -1;
 18         }
 19         printf("msqid:%d\n",msqid);
 20         return 0;
 21 }

实用消息队列实现进程间的通讯
使用有两种:

功能:将消息追加拷贝到消息队列的尾部
参数

msqid:指定了消息队列的id
Msgp:指定了消息的地址(消息包括消息id,消息体)
Msgsz:指定了消息体(mtext)的尺寸
Msgtyp:指定了要接收消息的类型。
Msgflg:
IPC_NOWAIT:非阻塞等待。如果消息队列的空间不足,立即返回,报错。
0        阻塞等待空间充足

返回值
0 成功
-1 错误errno被设置

Struct msgbuf{
    Long type;        //消息队列的类型,must be > 0
    Char text[1];        //消息队列的数据
}

Char text[1]; 字符数组,这个数组中只有一个元素,所以这个数组只能存放一个字符,那也说明一个消息只能带一个字符的数据。

Char message是变量,变量的空间里只能存放一个字符。
mtext 是数组的名字,也就是数组的首地址。

256个字符存放到数组里

p=(Struct msgbuf *)Malloc(sizeof(struct    msgbuf)+258-4);
Strcpy(p->text,”hello,world”);

举例

向消息队列发送一条消息

 1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/ipc.h>
  4 #include<sys/msg.h>
  5 #include<string.h>
  6 //定义消息的类型,程序员定义
  7 typedef struct msgbuf{
  8     long m_type;        //消息队列的类型,must be > 0
  9     char mtext[128];        //消息队列的数据
 10 }msg_t;
 11 int main(){
 12         key_t key;
 13         key=ftok(".",51);//使用键值获取消息队列的对象
 14         msg_t msg;
 15         if(key==-1){
 16                 perror("ftok");
 17                 return -1;
 18         }
 19         printf("key:0x%x\n",key);
 20         //使用键值获取消息队列
 21         int msqid=msgget(key,IPC_CREAT|0664);
 22         if(msqid==-1){
 23                 perror("msgget");
 24                 return -1;
 25         }
 26         printf("msqid:%d\n",msqid);
 27         //对消息初始化
 28         msg.m_type=3;
 29         strcpy(msg.mtext,"this is a test\n");
 30         //向消息队列发送一条消息
 31         int snd = msgsnd(msqid,&msg,strlen(msg.mtext),0);
 32         if(snd==-1){
 33                 perror("msgsnd");
 34                 return -1; 
35         }
 36
 37         return 0;
 38 }

2,从消息队列获取消息
Msgrcv

Size_t msgrcv(int msqis,void *msgp, size_t msgs,long msgtyp,int msgflg);

功能:从消息队列中移除一条消息,并将其放到msgp指定的buf中
参数

Msqid:指定消息队列
Msgs:指定了存储消息的缓冲区地址
Msgsz:指定了结构体中mtext字段的最大字节数
Msgtyp:指定了要接收的消息类型。
Msgflg:
IPC_NOWAIT: 非阻塞
        阻塞

返回值:
0 阻塞
-1 失败 errno被设置
成功 返回实际拷贝的mtext字段里的值

举例

从消息队列中获取消息,然后将消息输出到显示器

 1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/ipc.h>
  4 #include<sys/msg.h>
    #include<unistd.h>
  5 typedef struct msgbuf{
  6         long mtype;
  7         char mtext[128];
  8 }msg_t;
  9 int main(){
 10         key_t key;
 11         key=ftok(".",51);
 12         msg_t mb;
 13         if(key==-1){
 14                 perror("ftok");
 15                 return -1;
 16         }
 17         printf("key:0x%x\n",key);
 18         //使用键值获取消息队列
 19         int msqid=msgget(key,IPC_CREAT|0664);
 20         if(msqid==-1){
 21                 perror("msgget");
 22                 return -1;
 23         }
 24         printf("msqid:%d\n",msqid);
 25         //从消息队列中获取消息,然后将消息输出到显示器
 26         int rcv= msgrcv(msqid,&mb,128,3,0);
 27         if(rcv==-1){
 28                 perror("msgrcv");
 29                 return -1;
 30         }
 31         //将消息输出到屏幕
 32         write(1,mb.mtext,rcv);
 33         return 0;
 34 }

共享内存

#include <sys/shm.h>
int     shmget(key_t key, size_t size, int shmflg);

功能:分配一个共享内存段
参数

key:ftok(3)的返回值
Size:共享内存段的大小
Shmflg:
IPC_CREAT:如果共享内存段不存在,创建共享内存段。
O_CREAT|O_EXCL 和open(2)一样

返回值:
-1 失败 errno被设置
成功 共享内存的id

3,使用共享内存的id,将

 #include <sys/shm.h>
void *     shmat(int shmid, const void *shmaddr, int shmflg);

功能
参数:将共享内存段关联到进程的虚拟地址空间

Shmid:指定了关联的共享内存id
shmaddr:指定关联到进程的虚拟地址。NULL    由内核选择合适的地址。虚拟地址
shmflg:0    可读可写        SHM_RDONLY   只读

返回值
(void *)-1 错误。errno被设置
成功返回共享内存段的id

Int shmdt(const void *shmaddr);

功能:解除共享内存段的关联
参数
Shmaddr: 指定了共享内存段在虚拟地址空间的地址

返回值
成功 0
错误 -1 errno被设置

举例:

使用共享内存段实现进程间的通讯
有两个进程 进程A负责向内存中写入“this is a test!。。n”
进程B负责从内存中读出内存里的数据输出到显示器。

Shm1.c

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/ipc.h>
  4 #include<sys/shm.h>
  5 #include<string.h>
  6 int main(){
  7         key_t key;
  8         key=ftok(".",52);
  9         if(key==-1){
 10                 perror("ftok");
 11                 return -1;
 12         }
 13         printf("key0x:%x\n",key);
 14         //使用键值获取共享内存段的id
 15         int shmid= shmget(key,1024,IPC_CREAT);
 16         if(shmid==-1){
 17                 perror("shmget");
 18                 return -1;
 19         }
 20         printf("shmid:%d\n",shmid);
 21         //将共享内存段关联到进程的虚拟地址空间
 22         void *p=shmat(shmid,NULL,0);
 23         if(p==(void *)-1){
 24                 perror("shmat");
 25                 return -1;
 26         }
 27         strcpy(p,"this is a test..!\n");
 28         //解除关联
 29         getchar();
 30         shmdt(p);
 31         return 0;
 32 }

Shm2.c

 1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/ipc.h>
  4 #include<sys/shm.h>
  5 #include<string.h>
  6 int main(){
  7         key_t key;
  8         key=ftok(".",52);
  9         if(key==-1){
 10                 perror("ftok");
 11                 return -1;
 12         }
 13         printf("key0x:%x\n",key);
 14         //使用键值获取共享内存段的id
 15         int shmid= shmget(key,1024,IPC_CREAT);
 16         if(shmid==-1){
 17                 perror("shmget");
 18                 return -1;
 19         }
 20         printf("shmid:%d\n",shmid);
 21         //将共享内存段关联到进程的虚拟地址空间
 22         void *p=shmat(shmid,NULL,0);
 23         if(p==(void *)-1){
 24                 perror("shmat");
 25                 return -1;
 26         }
 27         printf("%s\n",(char* )p);
 28         //解除关联
 29         getchar();
 30         shmdt(p);
 31         return 0;
 32 }

举例

使用shmget(2)获取共享内存段的id

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/ipc.h>
  4 #include<sys/shm.h>
  5 int main(){
  6         key_t key;
  7         key=ftok(".",52);
  8         if(key==-1){
  9                 perror("ftok");
 10                 return -1;
 11         }
 12         printf("key0x:%x\n",key);
 13         //使用键值获取共享内存段的id
 14         int shmid= shmget(key,1024,IPC_CREAT);
 15         if(shmid==-1){
 16                 perror("shmget");
 17                 return -1;
 18         }
 19         printf("shmid:%d\n",shmid);
 20
 21         return 0;
 22 }

信号量集

#include <sys/ipc.h>
key_t     ftok(const char *path, int id);

功能:合成pathname和pro_id为system v ipc的键值
参数
Pathname:指定一个可访问的路径。只要文件是存在的,可访问的。
Proj_id:指定一个整数,取这个整数的低8位
返回值
成功 键值
失败 -1 errno被设置

举例

使用ftok(3)函数生成一个键值

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/ipc.h>
  4 int main(){
  5         key_t key;
  6         key=ftok(".",51);
  7         if(key==-1){
  8                 perror("ftok");
  9                 return -1;
 10         }
 11         printf("key:%d\n",key);
 12         return 0;
 13 }
~

使用键值获取内核管理的一个对象

二,网络基础

网络通讯中的两端 客户端 服务器端

服务器:服务器是硬件和软件的集合

逻辑 物理

网帧分为两类
以太网
令牌环网

目的地址和源地址 6个字节 MAC地址 物理地址
如何查看机器的地址:

Ifconfig        linux
ipconfig  /all      windows

网络协议的分层 TCP/IP协议
TCP/IP协议已经内嵌在网络操作系统内核里
TCP/IP协议风味4层或5层
应用层 传输层 网络层 链路层 , 物理测

图示

不同层次的协议.png
传输过程.png
地址通用模型.png
连接的建立.png
三次握手.png
通过路由器连接的两个网络.png
协议分层.png
以太网数据分用过程.png
arp请求应答格式.png
ftp两台主机.png
IP报文格式.png
IP地址分类.png
RFC894以太网帧.png
tcp包首部.png
tcp编程模型.png
udp编程模型.png
udp封装.png
udp首部.png

总结

一,system V ipc
消息队列
1,获取键值
2,使用键值获取消息队列的id
3,向消息队列发送消息
4,从消息队列获取消息
共享内存
二,网络基础
协议的分层
物理地址和逻辑地址

Responses