首页 > 其他分享 >原子操作CAS与锁实现

原子操作CAS与锁实现

时间:2022-11-21 22:56:53浏览次数:56  
标签:MAP 映射 CAS mmap 原子 int fd 内存 操作

(36条消息) 原子操作CAS与锁实现_going with the wind的博客-CSDN博客

 

锁和原子操作

(36条消息) 原子操作CAS与锁实现_摸鱼呀的博客-CSDN博客

 

 

CPU亲缘性

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <sched.h>
 4 
 5 #include <sys/syscall.h>
 6 
 7 
 8 // nginx.conf --> set affinity 0000 0000
 9 void process_affinity(int num) {
10 
11     
12     pid_t self_id = syscall(__NR_gettid);
13 
14     //fd_set
15     cpu_set_t mask;
16     CPU_ZERO(&mask);
17     CPU_SET(self_id % num, &mask);
18 
19     sched_setaffinity(self_id, sizeof(mask), &mask);
20     
21     while(1) usleep(1);
22 }
23 
24 
25 int main() {
26 
27     int num = sysconf(_SC_NPROCESSORS_CONF);
28 
29     printf("num: %d\n", num);
30 #if 0
31 
32     int i = 0;
33     pid_t pid = 0;
34     
35     for (i = 0;i < num/2;i ++) {
36 
37         pid = fork();
38         if (pid <= 0) {
39             break;
40         }
41 
42     }
43 
44     if (pid == 0) {
45         process_affinity(num);
46     }
47 
48 #else
49 
50     int i = 0;
51     
52     for (i = 0;i < num/2;i ++) {
53             
54         pthread_create();
55             
56     }
57 
58 #endif
59     printf("affinity.c: %d\n", pid);
60 
61     while(1) usleep(1);
62 
63 }

 

 

 

 

 

 

大文件如何快速的读进内存里面?

答:使用mmap,把文件映射(DMA,cpu不参与,零拷贝)到内存中来,然后使用多线程操作映射出来的内存。

 

⽂件内存映射mmap解决⼤⽂件快速读写问题

mmap函数主要⽤途有三个:

1、将⼀个普通⽂件映射到内存中,通常在需要对⽂件进⾏频繁读写时使⽤,这样⽤内存读写取代I/O读写,以获得较⾼的性能;

2、将特殊⽂件进⾏匿名内存映射,可以为关联进程提供共享内存空间;

3、为⽆关联的进程提供共享内存空间,⼀般也是将⼀个普通⽂件映射到内存中。

Linux提供了内存映射函数mmap, 它把⽂件内容映射到⼀段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对⽂件的读取和修改。

⼀、使⽤步骤

* ⽤open系统调⽤打开⽂件, 并返回描述符fd.

* ⽤mmap建⽴内存映射, 并返回映射⾸地址指针start.

* 对映射(⽂件)进⾏各种操作, 显⽰(printf), 修改(sprintf).

* ⽤munmap(void *start, size_t lenght)关闭内存映射.

* ⽤close系统调⽤关闭⽂件fd.

⼆、mmap函数⽤法

* 头⽂件:

#include <unistd.h>

#include <sys/mman.h>

* 函数:void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offsize);

参数start:指向欲映射的内存起始地址,通常设为 NULL,代表让系统⾃动选定地址,映射成功后返回该地址。

参数length:代表将⽂件中多⼤的部分映射到内存。

参数prot:映射区域的保护⽅式。可以为以下⼏种⽅式的组合:

PROT_EXEC 映射区域可被执⾏

PROT_READ 映射区域可被读取

PROT_WRITE 映射区域可被写⼊

PROT_NONE 映射区域不能存取

参数flags:影响映射区域的各种特性。在调⽤mmap()时必须要指定MAP_SHARED 或MAP_PRIVATE。

MAP_FIXED 如果参数start所指的地址⽆法成功建⽴映射时,则放弃映射,不对地址做修正。通常不⿎励⽤此旗标。

MAP_SHARED对映射区域的写⼊数据会复制回⽂件内,⽽且允许其他映射该⽂件的进程共享。

MAP_PRIVATE 对映射区域的写⼊操作会产⽣⼀个映射⽂件的复制,即私⼈的“写⼊时复制”(copy on write)对此区域作的任何修改都不会写回原来的⽂件内容。

MAP_ANONYMOUS建⽴匿名映射。此时会忽略参数fd,不涉及⽂件,⽽且映射区域⽆法和其他进程共享。

MAP_DENYWRITE只允许对映射区域的写⼊操作,其他对⽂件直接写⼊的操作将会被拒绝。

MAP_LOCKED 将映射区域锁定住,这表⽰该区域不会被置换(swap)。

参数fd:要映射到内存中的⽂件描述符。如果使⽤匿名内存映射时,即flags中设置了MAP_ANONYMOUS,fd设为-1。有些系统不⽀持匿名内存映射,则可以使⽤fopen打开/dev/zero⽂件,然后对该⽂件进⾏映射,可以同样达到匿名内存映射的效果。

参数offset:⽂件映射的偏移量,通常设置为0,代表从⽂件最前⽅开始对应,offset必须是分页⼤⼩的整数倍。

返回值:

若映射成功则返回映射区的内存起始地址,否则返回MAP_FAILED(-1),错误原因存于errno 中。

若映射成功则返回映射区的内存起始地址

错误代码:

EBADF 参数fd 不是有效的⽂件描述词

EACCES 存取权限有误。如果是MAP_PRIVATE 情况下⽂件必须可读,使⽤MAP_SHARED则要有PROT_WRITE以及该⽂件要能写⼊。

EINVAL 参数start、length 或offset有⼀个不合法。

EAGAIN ⽂件被锁住,或是有太多内存被锁住。

ENOMEM 内存不⾜。

* 系统调⽤mmap()⽤于共享内存的两种⽅式:

(1)使⽤普通⽂件提供的内存映射:

适⽤于任何进程之间。此时,需要打开或创建⼀个⽂件,然后再调⽤mmap()

典型调⽤代码如下:

fd=open(name, flag, mode); if(fd<0) ...

ptr=mmap(NULL, len , PROT_READ|PROT_WRITE, MAP_SHARED , fd , 0);

通过mmap()实现共享内存的通信⽅式有许多特点和要注意的地⽅,可以参看UNIX⽹络编程第⼆卷。

(2)使⽤特殊⽂件提供匿名内存映射:

适⽤于具有亲缘关系的进程之间。由于⽗⼦进程特殊的亲缘关系,在⽗进程中先调⽤mmap(),然后调⽤ fork()。那么在调⽤fork()之后,⼦进程继承⽗进程匿名映射后的地址空间,同样也继承mmap()返回的地址,这样,⽗⼦进程就可以通过映射区域进⾏通信了。注意,这⾥不是⼀般的继承关系。⼀般来说,⼦进程单独维护从⽗进程继承下来的⼀些变量。⽽mmap()返回的地址,却由⽗⼦进程共同维护。对于具有亲缘关系的进程实现共享内存最好的⽅式应该是采⽤匿名内存映射的⽅式。此时,不必指定具体的⽂件,只要设置相应的标志即可。

⼀. 概述

内存映射,简⽽⾔之就是将⽤户空间的⼀段内存区域映射到内核空间,映射成功后,⽤户对这段内存区域的修改可以直接反映到内核空间,相反,内核空间对这段区域的修改也直接反映⽤户空间。那么对于内核空间<---->⽤户空间两者之间需要⼤量数据传输等操作的话效率是⾮常⾼的。

⾸先,驱动程序先分配好⼀段内存,接着⽤户进程通过库函数mmap()来告诉内核要将多⼤的内存映射到内核空间,内核经过⼀系列函数调⽤后调⽤对应的驱动程序的file_operation中的mmap函数,在该函数中调⽤

remap_pfn_range()来建⽴映射关系。直⽩⼀点就是:驱动程序在mmap()中利⽤remap_pfn_range()函数将内核空间的⼀段内存与⽤户空间的⼀段内存建⽴映射关系。

⽤户空间mmap()函数:

void *mmap(void *start, length, int prot, int flags,int fd, off_t offset)

start:⽤户进程中要映射的某段内存区域的起始地址,通常为NULL(由内核来指定)

length:要映射的内存区域的⼤⼩

prot:期望的内存保护标志

flags:指定映射对象的类型

fd:⽂件描述符(由open函数返回)

offset:要映射的⽤户空间的内存区域在内核空间中已经分配好的的内存区域中的偏移。⼤⼩为PAGE_SIZE的整数倍

 

mmap方法

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <fcntl.h>
 4 #include <sys/mman.h>
 5 
 6 
 7 
 8 int main() {
 9 
10     int fd = open("./affinity.c", O_RDWR);
11 
12     //read(); write()
13 
14     unsigned char *addr = (unsigned char *)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
15 
16     printf("affinity: %s\n", addr);
17 
18     int i = 0;
19 
20     for (i = 0;i < 20;i ++) {
21         *(addr+i) = 'A' + i;
22     }
23 
24 }

 

标签:MAP,映射,CAS,mmap,原子,int,fd,内存,操作
From: https://www.cnblogs.com/cuijy1/p/16911168.html

相关文章

  • 第四章-线程间的同步操作 4-3 有时间限制的等待
    Waitingwithatimelimit1.Clocks时钟前面介绍的阻塞调用会将线程挂起一段(不确定的)时间,直到相应的事件发生。但在某些情况下,有时可能想要限制等待的时间。这里有......
  • 嵌入式可配置实时操作系统eCos
    ​​​​eCos是为嵌入式应用设计的无版税开放源代码的实时操作系统。eCos的高度可配置性,允许对操作系统进行定制,以精确地匹配应用需求,提供最佳运行时性能和最少硬件资源占用......
  • 文件操作
    1,程序设计中文件分为程序文件和数据文件数据文件根据数据的组织形式被称为文本文件或二进制文件       二进制文件:数据在内存中以二进制形式存在,不加转换的输......
  • 五分钟拿捏Python字典-Python3入门必备[字典详细操作]
    介绍在上一篇文章《​​Python3详细的数组基础操作-入门必备[列表的操作]​​》中讲解了Python的列表操作,这次接着唠唠Python数组中的字典,字典是Python的另一种可变容器......
  • ORA-14551: 无法在查询中执行 DML 操作
    最近在调试一个带DML操作的函数时,一直不成功,在PL/SQL中测试时没问题,通过SQL语句调用函数时就不行了,刚开始一直没找到原因,后来无意间把函数中捕获异常的代码注释掉,终于......
  • 加快软盘操作速度的汇编程序源代码
    ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;功能:加快软盘的操作速度;来源:《软件报》1995年合订本60页;作者:成都 ......
  • 区间简单操作
    求区间交和并给定一些区间,求出这些区间的交集和并集。交集一定连续。我们维护左端点和右端点,按照任意顺序扫描并维护即可。并集,先按照左端点排序,然后扫过去,维护最大......
  • 【广州华锐互动】石油钻井虚拟仿真操作实训平台
    石油钻井是一项流程繁杂、危险性高的工作,每一个操作人员都需要具备丰富的理论知识和实践操作能力,但是由于条件复杂,环境多变、设备昂贵等因素,很多企业或者学校都难以实现专......
  • js-004-表格操作
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>表格操作</title><style>.add{width:500px;height:......
  • ENVI新机器学习之异常探测分类工具操作手册
    异常探测是一种用于定位数据集中异常点的数据处理技术。异常值是指与数据集中的已知特征相比被认为不正常的值。例如,如果水是已知的特征,那么除水之外的任何东西都将被视为......