经常更改的网络数据包信息容器指针数组对象的volatile关键字C

经常更改的网络数据包信息容器指针数组对象的volatile关键字C,c,linux,C,Linux,我有一个这样的结构指针数组 struct packets *p=(struct packets *)malloc(sizeof(struct packets)*30); 该程序分为两个步骤 步骤1)在生产者线程中,我从RX环(从数据包MMAP)获取网络数据包 步骤2)并且在消费者线程中,我正在响应在步骤1中接收到的携带syn=1、ack=0的数据包 使用TX环(再次使用数据包MMAP) 还有像这样的算法 struct packets *p=(struct packets *)mal

我有一个这样的结构指针数组

   struct packets *p=(struct packets *)malloc(sizeof(struct packets)*30);
该程序分为两个步骤

步骤1)在生产者线程中,我从RX环(从数据包MMAP)获取网络数据包

步骤2)并且在消费者线程中,我正在响应在步骤1中接收到的携带syn=1、ack=0的数据包 使用TX环(再次使用数据包MMAP)

还有像这样的算法

   struct packets *p=(struct packets *)malloc(sizeof(struct packets)*30);
更新——很抱歉我写错了,真正的算法如下

    main()
      pthread_create step1;// Detached thread // while loop inside
      pthread_create step2;//Detached thread  // another while loop inside
    end main
struct packets*p
是接收和响应IP数据包的数据包列表。我听说过易失性对象会阻止编译器进行优化。*p只分配了一次,我使用
struct packets
中的字段来指示对
*p
数组的单个元素执行的最后一次操作(无论是生产者执行的最后一次操作还是消费者执行的最后一次操作),这是我在Google搜索我找到的以下信息中发现的易失性对象

volatile关键字用于防止编译器对可能以编译器无法确定的方式更改的对象应用任何优化。声明为volatile的对象在优化中被忽略,因为它们的值可以随时被当前代码范围之外的代码更改。26-Apr-2020

所以我想知道如果我使用
struct packets*p
指针作为volatile,是否可以,因为值会经常更改

我正在用C语言编写代码

struct packets*p
指针数组的分配只发生一次

更新

*p
是全局的。在接收器中只分配一次,就像pthread_一样

我还使用条件变量来向发送线程发送接收到数据包的信号


再次抱歉

数据包缓冲区是否被多个线程访问?如果没有,则不需要使用volatile关键字,因为编译器可以跟踪此变量的更改,事实上,允许编译器正常优化可能是一个好主意。它“频繁变化”的事实完全不相关

另一方面,如果您确实是从多个线程(或者说,一个中断服务例程)访问缓冲区,或者某个其他进程在您不知道的情况下修改了数据,那么您应该将缓冲区声明为volatile,但也可以使用类似于的方法来防止竞争条件

PS:在你更新了这个问题之后,第二个案例看起来肯定是真的。建议将其声明为volatile,并使用适当的同步


(其中一条评论中分享了这一点,并提供了关于volatile解决什么问题的更详细信息。)

我严重怀疑
volatile
是否是这里的一颗灵丹妙药。你要么需要原子,要么需要相互排斥的保护。这看起来、听起来和闻起来都像一个循环队列,应该实现适当的代码来管理所述队列。
volatile
最常见的用途是硬件更改检测。例如,对映射到某个地址位置的硬件端口的重复读取会返回不同的值,尽管编译器生成的代码或进程中运行的代码都不会进行这些底层更改
volatile
不是多线程程序中更改识别的灵丹妙药。您在internet上找到的关于
volatile
的所有信息中,99.5%要么是无关的,要么是完全错误的。关于
volatile
您需要知道的唯一一件事是:它仅与内存映射硬件寄存器一起工作。您是否有与内存映射硬件寄存器关联的变量?将其声明为volatile。你没有吗?不要声明任何易变的
volatile
。仅此而已。
volatile
如果在不同线程或信号处理程序中以及在正常处理中访问数据,则应使用。但是
volatile
关键字不能确保程序的不同部分以独占方式或原子方式访问数据。它只告诉编译器该值可以以编译器未知的方式更改,或者对该值的访问可能有副作用。@n.'degents'm.-FWIW-
volatile
也适用于其他方面。例如,我使用了
volatile
关键字来强制我的编译器在测试算法时避免优化掉变量,无论该变量是否与内存映射硬件有关。:)这从嵌入式系统的角度解释了问题:。除了它没有提到DMA缓冲区,它显然也是易失性的。任何一个有争议的人显然从未编写过DMA驱动程序……从数据包MMAP上的信息来看,它似乎是一个内核使网络数据包对进程可见的接口。进程中可能没有其他线程或系统中的其他用户进程更改数据,但操作系统和硬件本身可能正在更改数据。不幸的是,我最初发现的文档并不清楚接口。自2011年以来,线程一直是C标准的一部分。互斥锁通常不包含任何易失性,它包含一个内存屏障。关于编译器优化的谬论是编译器不是唯一进行优化的东西。CPU自己进行优化。你需要一个记忆屏障来防止这些。该标志还需要是原子性的。“它的目的是向编译器指示这段内存可能是在上下文之外访问的。”这里的问题是,如果它是从另一个线程在上下文之外访问的,那么就存在争用条件。要停止竞争条件,请使用互斥锁或类似的同步机制。一旦你有了同步机制,你就不需要
volatile
@n.“代词m”<代码>易失性在这种情况下从未用于实现重新进入