Linux下__attribute__((aligned(n)))的使用

本文深入探讨了GCC扩展关键字__attribute__的使用方法,包括如何指定变量和结构体的对齐方式,取消编译优化对齐,以及示例代码和测试结果。通过具体示例,如使用__aligned__和__packed__属性,展示了如何控制内存布局,提高数据访问效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关键字__attribute__允许你在定义struct、union、变量等类型时指定特殊属性。此关键字后面是跟着双括号括起来的属性说明。__attribute__不属于标准C语言,它是GCC对C语言的一个扩展用法。

你可以在其关键字之前和之后使用"__"指定这些属性中的一个,这样允许你在头文件中使用这些属性,而不必担心可能的同名宏。例如你可以使用__aligned__代替aligned。

        __attribute__((aligned(n))):此属性指定了指定类型的变量的最小对齐(以字节为单位)。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。

注意:对齐属性的有效性会受到链接器(linker)固有限制的限制,即如果你的链接器仅仅支持8字节对齐,即使你指定16字节对齐,那么它也仅仅提供8字节对齐。

 __attribute__((packed)):此属性取消在编译过程中的优化对齐。

关于C++内存对齐介绍可以参考: https://blog.csdn.net/fengbingchun/article/details/81270326

 以下是测试代码(sample_attribute_aligned.cpp):

#include <iostream>

int main()
{
	struct S1 {short f[3];};
	struct S2 {short f[3];} __attribute__((aligned(64)));
	struct S5 {short f[40];} __attribute__((aligned(64)));
	fprintf(stdout, "S1 size: %d, S2 size: %d, S5 size: %d\n",
		sizeof(struct S1), sizeof(struct S2), sizeof(struct S5)); // 6, 64, 128

	typedef int more_aligned_int __attribute__((aligned(16)));
	fprintf(stdout, "aligned: %d, %d\n", alignof(int), alignof(more_aligned_int)); // 4, 16

	struct S3 {more_aligned_int f;};
	struct S4 {int f;};
	fprintf(stdout, "S3 size: %d, S4 size: %d\n", sizeof(struct S3), sizeof(struct S4)); // 16, 4

	int arr[2] __attribute__((aligned(16))) = {1, 2};
	fprintf(stdout, "arr size: %d, arr aligned: %d\n", sizeof(arr), alignof(arr)); // 8, 16

	struct S6 {more_aligned_int f;} __attribute__((packed));
	fprintf(stdout, "S6 size: %d\n", sizeof(struct S6)); // 4

	char c __attribute__((aligned(16))) = 'a';
	fprintf(stdout, "c size: %d, aligned: %d\n", sizeof(c), alignof(c)); // 1, 16

	struct S7 {double f;} __attribute__((aligned(4)));
	fprintf(stdout, "S7 size: %d, algined: %d\n", sizeof(struct S7), alignof(struct S7)); // 8, 8

	struct S8 {double f;} __attribute__((__aligned__(32)));
	fprintf(stdout, "S8 size: %d, algined: %d\n", sizeof(struct S8), alignof(struct S8)); // 32, 32

	return 0;
}

CMakeLists.txt文件内容如下:

PROJECT(samples_cplusplus)
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)

# 支持C++11
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -O2 -std=c11")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -g -Wall -O2 -std=c++11")

INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})

FILE(GLOB samples ${PROJECT_SOURCE_DIR}/*.cpp)

FOREACH (sample ${samples})
	STRING(REGEX MATCH "[^/]+$" sample_file ${sample})
	STRING(REPLACE ".cpp" "" sample_basename ${sample_file})
	ADD_EXECUTABLE(test_${sample_basename} ${sample})
	TARGET_LINK_LIBRARIES(test_${sample_basename} pthread)
ENDFOREACH()

build.sh脚本内容如下:

#! /bin/bash

real_path=$(realpath $0)
dir_name=`dirname "${real_path}"`
echo "real_path: ${real_path}, dir_name: ${dir_name}"

new_dir_name=${dir_name}/build
mkdir -p ${new_dir_name}
cd ${new_dir_name}
cmake ..
make

cd -

编译及测试方法如下:首先执行build.sh,然后再执行./build/test_sample_attribute_aligned即可。

GitHubhttps://github.com/fengbingchun/Linux_Code_Test 

`NFQNL_COPY_PACKET`是一个标志,用于指示内核将数据包复制到用户空间。它是在使用Netfilter队列机制时使用的标志之一。当使用此标志时,内核将数据包的副本发送到用户空间,以便用户空间应用程序可以对其进行处理。以下是一个使用`NFQNL_COPY_PACKET`标志的示例: ```c #include <stdio.h> #include <stdlib.h> #include <netinet/in.h> #include <linux/types.h> #include <linux/netfilter.h> #include <libnetfilter_queue/libnetfilter_queue.h> /* Callback function */ static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { struct nfqnl_msg_packet_hdr *ph; u_int32_t id; struct nfqnl_msg_packet_hw *hwph; u_int8_t *payload; int payload_len; ph = nfq_get_msg_packet_hdr(nfa); if (ph) { id = ntohl(ph->packet_id); printf("hw_protocol=0x%04x hook=%u id=%u ", ntohs(ph->hw_protocol), ph->hook, id); } hwph = nfq_get_packet_hw(nfa); if (hwph) { int i, hlen = ntohs(hwph->hw_addrlen); printf("hw_src_addr="); for (i = 0; i < hlen-1; i++) printf("%02x:", hwph->hw_addr[i]); printf("%02x ", hwph->hw_addr[hlen-1]); } payload_len = nfq_get_payload(nfa, &payload); if (payload_len >= 0) printf("payload_len=%d ", payload_len); fputc('\n', stdout); /* Copy packet to userspace */ return nfq_set_verdict(qh, id, NF_ACCEPT, payload_len, payload); } int main(int argc, char **argv) { struct nfq_handle *h; struct nfq_q_handle *qh; struct nfnl_handle *nh; int fd; int rv; char buf[4096] __attribute__ ((aligned)); printf("opening library handle\n"); h = nfq_open(); if (!h) { fprintf(stderr, "error during nfq_open()\n"); exit(1); } printf("unbinding existing nf_queue handler for AF_INET (if any)\n"); if (nfq_unbind_pf(h, AF_INET) < 0) { fprintf(stderr, "error during nfq_unbind_pf()\n"); exit(1); } printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n"); if (nfq_bind_pf(h, AF_INET) < 0) { fprintf(stderr, "error during nfq_bind_pf()\n"); exit(1); } printf("binding this socket to queue '0'\n"); qh = nfq_create_queue(h, 0, &callback, NULL); if (!qh) { fprintf(stderr, "error during nfq_create_queue()\n"); exit(1); } printf("setting copy_packet mode\n"); if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) { fprintf(stderr, "can't set packet_copy mode\n"); exit(1); } fd = nfq_fd(h); while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) { printf("pkt received\n"); nfq_handle_packet(h, buf, rv); } printf("unbinding from queue 0\n"); nfq_destroy_queue(qh); printf("closing library handle\n"); nfq_close(h); exit(0); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值