当前位置: 首页 > news >正文

南京鼓楼做网站的公司民生热点新闻

南京鼓楼做网站的公司,民生热点新闻,哪里有前端技术培训,适合夫妻看的哔哩哔哩电视剧目录 认识system V: system V共享内存: 共享内存的基本原理: 共享内存的数据结构: 共享内存的建立与释放: 共享内存的建立: 共享内存的释放: 共享内存的关联: 共享内存的去关联…

目录

认识system V:

system V共享内存:

 共享内存的基本原理:

共享内存的数据结构:

共享内存的建立与释放:

共享内存的建立:

 共享内存的释放:

共享内存的关联: 

 共享内存的去关联:

用共享内存实现serve&client通信:

 system V消息队列:

消息队列基本原理:

消息队列数据结构:

消息队列的创建:

消息队列的释放:

向消息队列发送数据:

从消息队列获取数据:

system信号量:

信号量相关概念:

信号量数据结构:

信号量集的创建:

 信号量集的删除:

 信号量集的操作:

进程互斥 


认识system V:

对于进程间通信,想必管道大家再熟悉不过了,对于管道这种通信方式,其实是对底层代码的一种复用,linux工程师借助类似文件缓冲区的内存空间实现了管道,其实也算偷了一个小懒,随着linux的发展,linux正式推出了System V来专门进行进程间通信,它和管道的本质都是一样的,都是让不同的进程看到同一份资源。

system V通信的3种通信方式:

1.system V共享内存 ()

2.system V消息队列 ()

3.system V信号量 ()

上述中的共享内存和消息队列主要用于传输数据,而信号量则是用于保证进程间的同步与互斥,虽然看起来信号量和通信没关联,但其实它也属于通信的范畴。

system V共享内存:

 共享内存的基本原理:

之前说的到了通信的原理都是让不同的进程看到同一份资源,共享内存让进程看到同一份资源的方法就是,在物理内存中申请一块空间,名为共享内存,然后让这块空间与需要通信的进程的页表建立映射,再在进程的虚拟地址的栈区和堆区中间的共享区,开辟一段空间,将该空间的地址页表对应的位置,这样虚拟地址就和物理地址建立了联系,让不同的进程看到了同一份资源。

注意:这里说的开辟物理空间和建立页表映射关系,都是由操作系统来完成。

共享内存的数据结构:

系统中可能不止一对进程需要通信,一块共享内存只能支持两个进程通信,所以操作系统是支持申请多个共享内存的,而多个共享内存被操作系统管理,所以操作系统中一定有管理共享内存的内核数据结构:

struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment (bytes) */
__kernel_time_t shm_atime; /* last attach time */
__kernel_time_t shm_dtime; /* last detach time */
__kernel_time_t shm_ctime; /* last change time */
__kernel_ipc_pid_t shm_cpid; /* pid of creator */
__kernel_ipc_pid_t shm_lpid; /* pid of last operator */
unsigned short shm_nattch; /* no. of current attaches */
unsigned short shm_unused; /* compatibility */
void *shm_unused2; /* ditto - used by DIPC */
void *shm_unused3; /* unused */
};

当我们申请一块共享内存,system V为了能让不同的进程看到这块共享内存,每个共享内存申请时都会有一个key值,用于系统标志这块共享内存的唯一性。

可以看到上面共享内存数据结构中,第一个成员是shm_permshm_perm是一个ipc_perm类型的结构体变量,ipc_perm中存放了每个共享内存的key,ipc_perm的结构如下:

struct ipc_perm{__kernel_key_t  key;__kernel_uid_t  uid;__kernel_gid_t  gid;__kernel_uid_t  cuid;__kernel_gid_t  cgid;__kernel_mode_t mode;unsigned short  seq;
};

共享内存的建立与释放:

共享内存的建立大致为以下两步:

1.在物理空间中开辟一块共享内存空间。

2.将该物理空间与进程虚拟地址空间通过页表建立映射关系。(挂载)

共享内存的释放大致为以下两步: 

1.将该物理空间和进程虚拟地址空间取关联,取消页表映射。(去挂载)

2.释放共享空间,将物理内存还给操作系统。

共享内存的建立:

共享内存的建立需要使用smhget函数:

smhget参数说明:

key:表示待创建共享内存在系统的唯一标识。

size:表示想要申请的共享内存的大小。(建议4096的整数倍)

shmflg:表示创建共享内存的方式。

smhget返回值说明:

若创建成功则返回共享内存的描述符smhid(用户层的,和key不同) 

若创建失败则返回 -1

注意key值是需要我们自己传入的,我们可以想传什么就传什么,但key不可重复,所以建议使用ftok函数来取到合适的key:

 注意:ftok函数是将一个路径pathname和一个proj_id通过一个特定的函数转换成key值。

传入shmget函数的第三个参数shmflg,常用的组合方式有以下两种: 

组合方式作用
IPC_CREAT如果内核中不存在键值与key相等的共享内存,则新建一个共享内存并返回该共享内存的句柄;如果存在这样的共享内存,则直接返回该共享内存的句柄
IPC_CREAT|IPC_EXCL如果内核中不存在键值与key相等的共享内存,则新建一个共享内存并返回该共享内存的句柄;如果存在这样的共享内存,则出错返回

这两种奇怪的区分到底有什么用呢?

若是第一种方式拿到了一个描述符,则说明该共享内存一定是旧的。

若是第二种方式拿到了一个描述符,则说明该共享内存一定是新的。

所以我们用第二种组合方式来创建共享内存,用第一种组合方式来找到一个共享内存。

共享内存创建好后,我们是可以通过ipcs命令来进行查询的:

 ipcs命令选项介绍:

  • -q:列出消息队列相关信息。
  • -m:列出共享内存相关信息。
  • -s:列出信号量相关信息。

不加选项默认全部列出:

 图中每列信息如下:

标题含义
key系统区别各个共享内存的唯一标识
shmid共享内存的用户层id(句柄)
owner共享内存的拥有者
perms共享内存的权限
bytes共享内存的大小
nattch关联共享内存的进程数
status共享内存的状态

现在我们编写一个简单的程序来创建一个共享内存,并打印出它的key和描述符:

#include <iostream>
#include <cstdio>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>const char* pathname = "/home/sxk/linux2/24_6_6";
int proj_id = 0x66;int main()
{//得出keykey_t key = ftok(pathname,proj_id);if(key < 0){perror("ftok");}//创建共享内存int shmid = shmget(key,4096,IPC_CREAT);if(shmid < 0){perror("shmget");}//打印出共享内存的key和shmidprintf("key:   %x\n",key);printf("shmid: %d\n",shmid);sleep(10);return 0;
}

运行结果:

 共享内存的释放:

先介绍一个共享内存的重要特性:

共享内存不随程序的结束而释放。

 所以,当我们的程序结束后共享内存仍然存在:

如果想要释放这个共享内存有两种方法:

1.使用 ipcrm -m 描述符  指令来删除指定的共享内存

2.在代码中使用shmctl函数:

shmctl函数参数选项介绍: 

  • 第一个参数shmid,表示所控制共享内存的用户级标识符。
  • 第二个参数cmd,表示具体的控制动作。
  • 第三个参数buf,用于获取或设置所控制共享内存的数据结构

shmctl函数的返回值说明:

  • shmctl调用成功,返回0。
  • shmctl调用失败,返回-1。

第二个参数cmd常用的几个选项如下:

选项作用
IPC_STAT获取共享内存的当前关联值,此时参数buf作为输出型参数
IPC_SET在进程有足够权限的前提下,将共享内存的当前关联值设置为buf所指的数据结构中的值
IPC_RMID删除共享内存段

修改之前的代码,创建共享内存2秒后删除共享内存:

共享内存的关联: 

 共享内存在物理空间创建好后,还需将物理内存的地址与进程的虚拟地址空间中的共享区的地址,通过页表映射建立联系,这样之后进程才能访问这片共享内存。

通过shmat函数来建立映射关系

shmat函数的参数说明:

  • 第一个参数shmid,表示待关联共享内存的用户级标识符。
  • 第二个参数shmaddr,指定共享内存映射到进程地址空间的某一地址,通常设置为NULL,表示让内核自己决定一个合适的地址位置。
  • 第三个参数shmflg,表示关联共享内存时设置的某些属性。

shmat函数的返回值说明:

  • shmat调用成功,返回共享内存映射到进程地址空间中的起始地址。
  • shmat调用失败,返回(void*)-1。

其中,作为shmat函数的第三个参数传入的常用的选项有以下三个:

选项作用
SHM_RDONLY关联共享内存后只进行读取操作
SHM_RND若shmaddr不为NULL,则关联地址自动向下调整为SHMLBA的整数倍。公式:shmaddr-(shmaddr%SHMLBA)
0默认为读写权限

 共享内存的去关联:

使用shmdt函数来去关联:

shmat函数参数介绍:

  • shmaddr:表示需要去关联的共享内存

shmat函数的返回值

  • 若去关联成功, 则返回0
  • 若去关联失败, 则返回-1

用共享内存实现serve&client通信:

serve端负责创建共享内存,并收消息,client,负责发消息。

serve.cc:

#include <iostream>
#include <cstdio>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>const char* pathname = "/home/sxk/linux2/24_6_6";
int proj_id = 0x66;int main()
{//得出keykey_t key = ftok(pathname,proj_id);if(key < 0){perror("ftok");}//创建共享内存int shmid = shmget(key,4096,IPC_CREAT|IPC_EXCL|0666);if(shmid < 0){perror("shmget");}//打印出共享内存的key和shmidprintf("key:   %x\n",key);printf("shmid: %d\n",shmid);sleep(5);//与共享内存关联char* msg = (char*)shmat(shmid,NULL,0);if(msg == (void*)-1){perror("shmat");}//开始读消息std::cout<<"serve begin read msg :"<<std::endl;while(1){std::cout<<msg<<std::endl;sleep(1);}//读完,去关联int n = shmdt(msg);if(n < 0){perror("shmdt");}//释放共享内存int t = shmctl(shmid,IPC_RMID,NULL);if(t < 0){perror("shmctl");}return 0;
}

client.cc:

#include <iostream>
#include <cstdio>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>const char* pathname = "/home/sxk/linux2/24_6_6";
int proj_id = 0x66;int main()
{//获取keykey_t key = ftok(pathname,proj_id);if(key < 0){perror("ftok");}//获取共享内存int shmid = shmget(key,4096,IPC_CREAT);if(shmid < 0){   perror("shmget");}//与共享内存关联指定shmid,不指定地址起始位置,读写权限char* msg = (char*)shmat(shmid,NULL,0);if(msg == (void*)-1){  perror("shmat");}//开始发送消息char a = 'A';int i = 0;while(a < 'Z'){msg[i] = a + i;i++;sleep(1);}//发送完毕,去关联int t = shmdt(msg);if(t < 0 ){perror("shmdt");}return 0;
}

运行结果:

 system V消息队列:

消息队列基本原理:

消息队列实际上就是在系统当中创建了一个队列,队列当中的每个成员都是一个数据块,这些数据块都由类型和信息两部分构成,两个互相通信的进程通过某种方式看到同一个消息队列,这两个进程向对方发数据时,都在消息队列的队尾添加数据块,这两个进程获取数据块时,都在消息队列的队头取数据块。

总结一下:

  1. 消息队列提供了一个从一个进程向另一个进程发送数据块的方法。
  2. 每个数据块都被认为是有一个类型的,接收者进程接收的数据块可以有不同的类型值。
  3. 和共享内存一样,消息队列的资源也必须自行删除,否则不会自动清除,因为system V IPC资源的生命周期是随内核的。

消息队列数据结构:

当然,系统当中也可能会存在大量的消息队列,系统一定也要为消息队列维护相关的内核数据结构。

消息队列的数据结构如下:

struct msqid_ds {struct ipc_perm msg_perm;struct msg *msg_first;      /* first message on queue,unused  */struct msg *msg_last;       /* last message in queue,unused */__kernel_time_t msg_stime;  /* last msgsnd time */__kernel_time_t msg_rtime;  /* last msgrcv time */__kernel_time_t msg_ctime;  /* last change time */unsigned long  msg_lcbytes; /* Reuse junk fields for 32 bit */unsigned long  msg_lqbytes; /* ditto */unsigned short msg_cbytes;  /* current number of bytes on queue */unsigned short msg_qnum;    /* number of messages in queue */unsigned short msg_qbytes;  /* max number of bytes on queue */__kernel_ipc_pid_t msg_lspid;   /* pid of last msgsnd */__kernel_ipc_pid_t msg_lrpid;   /* last receive pid */
};

可以看到消息队列数据结构的第一个成员是msg_perm,它和shm_perm是同一个类型的结构体变量,ipc_perm结构体的定义如下:

struct ipc_perm{__kernel_key_t  key;__kernel_uid_t  uid;__kernel_gid_t  gid;__kernel_uid_t  cuid;__kernel_gid_t  cgid;__kernel_mode_t mode;unsigned short  seq;
};

消息队列的创建:

创建消息队列我们需要用msgget函数:

msgget函数参数介绍:

key:表示带创建消息队列在系统的唯一标识。(跟共享内存差不多)

msgflg:和shmget的第三个参数一样。

msgget函数返回值介绍:

创建消息队列成功则返回该消息队列的描述符。(用户级)

消息队列的释放:

释放消息队列我们需要用msgctl函数:

msgctl和shmctl用法基本相同。

向消息队列发送数据:

向消息队列发送数据我们需要用msgsnd函数:

msgsnd函数的参数说明:

  • 第一个参数msqid,表示消息队列的用户级标识符。
  • 第二个参数msgp,表示待发送的数据块。
  • 第三个参数msgsz,表示所发送数据块的大小
  • 第四个参数msgflg,表示发送数据块的方式,一般默认为0即可。

msgsnd函数的返回值说明:

  • msgsnd调用成功,返回0。
  • msgsnd调用失败,返回-1。

其中msgsnd函数的第二个参数必须为以下结构:

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

注意: 该结构当中的第二个成员mtext即为待发送的信息,当我们定义该结构时,mtext的大小可以自己指定。

从消息队列获取数据:

从消息队列获取数据我们需要用msgrcv函数:

msgrcv函数的参数说明:

  • 第一个参数msqid,表示消息队列的用户级标识符。
  • 第二个参数msgp,表示获取到的数据块,是一个输出型参数。
  • 第三个参数msgsz,表示要获取数据块的大小
  • 第四个参数msgtyp,表示要接收数据块的类型。

msgrcv函数的返回值说明:

  • msgsnd调用成功,返回实际获取到mtext数组中的字节数。
  • msgsnd调用失败,返回-1。

system信号量:

信号量相关概念:

由于进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系叫做进程互斥。


系统中某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源。

在进程中涉及到临界资源的程序段叫临界区。

IPC资源必须删除,否则不会自动删除,因为system V IPC的生命周期随内核。

信号量数据结构:

在系统当中也为信号量维护了相关的内核数据结构:

struct semid_ds {struct ipc_perm sem_perm;       /* permissions .. see ipc.h */__kernel_time_t sem_otime;      /* last semop time */__kernel_time_t sem_ctime;      /* last change time */struct sem  *sem_base;      /* ptr to first semaphore in array */struct sem_queue *sem_pending;      /* pending operations to be processed */struct sem_queue **sem_pending_last;    /* last pending operation */struct sem_undo *undo;          /* undo requests on this array */unsigned short  sem_nsems;      /* no. of semaphores in array */
};

信号量数据结构的第一个成员也是ipc_perm类型的结构体变量,ipc_perm结构体的定义如下:

struct ipc_perm{__kernel_key_t  key;__kernel_uid_t  uid;__kernel_gid_t  gid;__kernel_uid_t  cuid;__kernel_gid_t  cgid;__kernel_mode_t mode;unsigned short  seq;
};

信号量集的创建:

创建信号量集我们需要用semget函数: 

创建信号量集也需要使用ftok函数生成一个key值,这个key值作为semget函数的第一个参数。

semget函数的第二个参数nsems,表示创建信号量的个数。

semget函数的第三个参数,与创建共享内存时使用的shmget函数的第三个参数相同。

信号量集创建成功时,semget函数返回的一个有效的信号量集标识符(用户层标识符)。
信号量集的删除

 信号量集的删除:

 删除信号量集我们需要用semctl函数:

 信号量集的操作:

 对信号量集进行操作我们需要用semop函数:

进程互斥 

进程间通信通过共享资源来实现,这虽然解决了通信的问题,但是也引入了新的问题,那就是通信进程间共用的临界资源,若是不对临界资源进行保护,就可能产生各个进程从临界资源获取的数据不一致等问题。

保护临界资源的本质是保护临界区,我们把进程代码中访问临界资源的代码称之为临界区,信号量就是用来保护临界区的,信号量分为二元信号量和多元信号量。

信号量本质是一个计数器,在二元信号量中,信号量的个数为1(相当于将临界资源看成一整块),二元信号量本质解决了临界资源的互斥问题,以下面的伪代码进行解释: 

 根据以上代码,当进程A申请访问共享内存资源时,如果此时sem为1(sem代表当前信号量个数),则进程A申请资源成功,此时需要将sem减减,然后进程A就可以对共享内存进行一系列操作,但是在进程A在访问共享内存时,若是进程B申请访问该共享内存资源,此时sem就为0了,那么这时进程B会被挂起,直到进程A访问共享内存结束后将sem加加,此时才会将进程B唤起,然后进程B再对该共享内存进行访问操作。

在这种情况下,无论什么时候都只会有一个进程在对同一份共享内存进行访问操作,也就解决了临界资源的互斥问题。

实际上,代码中计数器sem减减的操作就叫做P操作,而计数器加加的操作就叫做V操作,P操作就是申请信号量,而V操作就是释放信号量。

感谢阅读!

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:腾讯云自媒体同步曝光计划 - 腾讯云开发者社区-腾讯云


文章转载自:
http://unaging.mkbc.cn
http://yen.mkbc.cn
http://eparch.mkbc.cn
http://acta.mkbc.cn
http://mihrab.mkbc.cn
http://unduly.mkbc.cn
http://predicative.mkbc.cn
http://senile.mkbc.cn
http://ayc.mkbc.cn
http://cogon.mkbc.cn
http://impugnable.mkbc.cn
http://micropyrometer.mkbc.cn
http://enteroid.mkbc.cn
http://dwell.mkbc.cn
http://wifehood.mkbc.cn
http://spadefoot.mkbc.cn
http://burhel.mkbc.cn
http://radiotoxicology.mkbc.cn
http://gibberish.mkbc.cn
http://donkey.mkbc.cn
http://paedobaptist.mkbc.cn
http://greenland.mkbc.cn
http://igloo.mkbc.cn
http://meretrix.mkbc.cn
http://epiclesis.mkbc.cn
http://adiaphoresis.mkbc.cn
http://eland.mkbc.cn
http://thrombocytosis.mkbc.cn
http://trichroic.mkbc.cn
http://ocs.mkbc.cn
http://sluggard.mkbc.cn
http://photochemical.mkbc.cn
http://roborant.mkbc.cn
http://didymium.mkbc.cn
http://hydrid.mkbc.cn
http://necrophagous.mkbc.cn
http://miquelon.mkbc.cn
http://keratalgia.mkbc.cn
http://decapod.mkbc.cn
http://cabob.mkbc.cn
http://fluorimetry.mkbc.cn
http://afore.mkbc.cn
http://konak.mkbc.cn
http://carex.mkbc.cn
http://vespucci.mkbc.cn
http://overdominance.mkbc.cn
http://phycocyan.mkbc.cn
http://squiffed.mkbc.cn
http://maladaptive.mkbc.cn
http://immune.mkbc.cn
http://promptitude.mkbc.cn
http://lawfulness.mkbc.cn
http://squaloid.mkbc.cn
http://soulless.mkbc.cn
http://sisterhood.mkbc.cn
http://boat.mkbc.cn
http://familial.mkbc.cn
http://avidly.mkbc.cn
http://polycentric.mkbc.cn
http://modelly.mkbc.cn
http://halfpence.mkbc.cn
http://teentsy.mkbc.cn
http://ossuarium.mkbc.cn
http://camphoric.mkbc.cn
http://pneumatics.mkbc.cn
http://purply.mkbc.cn
http://unbudging.mkbc.cn
http://passively.mkbc.cn
http://stenotypist.mkbc.cn
http://quaintness.mkbc.cn
http://octode.mkbc.cn
http://adulterant.mkbc.cn
http://epsilon.mkbc.cn
http://obdurately.mkbc.cn
http://scowl.mkbc.cn
http://distinctly.mkbc.cn
http://risky.mkbc.cn
http://lollop.mkbc.cn
http://spermagonium.mkbc.cn
http://hooter.mkbc.cn
http://beside.mkbc.cn
http://bauson.mkbc.cn
http://uninstall.mkbc.cn
http://optoelectronics.mkbc.cn
http://organa.mkbc.cn
http://overelaborate.mkbc.cn
http://harrumph.mkbc.cn
http://provisionality.mkbc.cn
http://hesse.mkbc.cn
http://reawaken.mkbc.cn
http://architect.mkbc.cn
http://ugaritic.mkbc.cn
http://ephemeron.mkbc.cn
http://celestialize.mkbc.cn
http://prefectorial.mkbc.cn
http://sepalous.mkbc.cn
http://misremember.mkbc.cn
http://condenses.mkbc.cn
http://entrails.mkbc.cn
http://gomphiasis.mkbc.cn
http://www.15wanjia.com/news/76828.html

相关文章:

  • 商城网站建设合同参考消息今天新闻
  • 视觉设计网站建设申请百度收录网址
  • ag网站开发个人推广app的妙招
  • 明港seo公司上海seo推广公司
  • 优秀电子商务网站正规网站建设服务
  • 电子商务网站建设及维护软文生成器
  • 做分销网站推广平台排名前十名
  • 深圳十大集团公司排名界首网站优化公司
  • 潜江网站建设查淘宝关键词排名软件
  • 如何网站建设代写文章质量高的平台
  • 手机怎么创网站免费下载百度学术论文查重入口
  • 厦门做网站排名第三方关键词优化排名
  • 做外贸需要什么网站360优化大师旧版本
  • 张槎建网站服务免费关键词排名优化软件
  • wordpress 插件发文章seo的培训网站哪里好
  • 龙岗网站制作讯息网站设计模板网站
  • 做网站公司排名青岛百度网站排名
  • 宝安电子厂做高端网站seo顾问服务公司站长
  • 信阳网站建设制作公司网络推广员好做吗
  • 晋城市公共事业建设局网站最让顾客心动的促销活动
  • 十年经验网站开发企业seo入门教程seo入门
  • 备案个人可以做视频网站seo 网站优化推广排名教程
  • 如何做好网站内链爱站网注册人查询
  • 网站域名费会计分录怎么做西安网络推广外包公司
  • 建网站和开发软件哪个难seo专业学校
  • 企业网站咋做seo专业推广
  • table做网站的好处网络营销客服主要做什么
  • 什么是网站单页怎么引流怎么推广自己的产品
  • 怎样建立自己的网站地推十大推广app平台
  • 稿定设计网站官网搜索关键词