由System V消息队列引发的思考__GNU_SOURCE

本文探讨了在使用System V消息队列时遇到的结构体msgbuf在<sys/msg.h>中未定义的问题。通过分析发现,需要定义__GNU_SOURCE宏才能启用相关结构体的声明。然而,__GNU_SOURCE是glibc内部宏,不适合在应用程序中直接定义,正确做法是定义_GNU_SOURCE或在编译时添加-D _GNU_SOURCE选项。文章还介绍了功能测试宏在glibc头文件中的作用,以及它们如何影响标准特性的启用。

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

System V消息队列引发的思考

最近看unp的卷2,自己写了一下书上的例子。因为作者是直接包含他自己写的头文件而书中并没有列出来,所以只能自己man函数而得到相应的头文件。那么问题来了,

struct msgbuf{

  long mtype;

  char mtext[1];

}

书上说这个结构体包含在<sys/msg.h>中,但恰恰就是在这个结构体出了问题。还是先上源代码。

第一版的编译是错误的源代码:

#include<stdio.h>

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h>

#include<stdlib.h>

 

typedef unsigned long ulong_t;

 

int main()

{

        int msqid;

        struct msqid_ds info;

        struct msgbuf buf;

        int oflag=0664|IPC_CREAT;

 

        if((msqid=msgget(IPC_PRIVATE,oflag))<0)

                perror("msgget error");

 

        buf.mtype=1;

        buf.mtext[0]=1;

 

        if(msgsnd(msqid,&buf,1,0)<0)

                perror("msgsnd error");

 

        if(msgctl(msqid,IPC_STAT,&info)<0)

                perror("msgctl error");

 

        printf("read-write:%03o,cbytes=%lu,qnum=%lu,qbytes=%lu\n",info.msg_perm.mode&0777,(ulong_t)info.msg_cbytes,(ulong_t)info.msg_qnum,

        (ulong_t)info.msg_qbytes);

 

        system("ipcs -q");

 

        if(msgctl(msqid,IPC_RMID,NULL))

                perror("msgctl error");

 

        exit(0);

 

}

编译后显示如下:

 

明明我包含了头文件<sys/msg.h>而书上说了该结构体在该文件中定义了,难道书上写错了

下面用sed命令来看一下<sys/msg.h>头文件中关于msgbuf结构体:


由上图可知,msgbuf显然是在头文件中定义了的。但是,当你仔细看时就会发现在结构体上面的一句#ifdef __USE_GNU也就是说要定义了__USE_GNU了后才会声明msgbuf结构体

但是当我定义了__USE_GNU了后就还是同样的错误。Google了一下,上面是这样说的

This is wrong, __USE_GNU is glibc internal macro that shouldn't be ever

defined by apps.

The way to select GNU feature set in glibc headers is to define _GNU_SOURCE,

either before including first include header in the source .c/.C file,

or by defining it on the command line (-D_GNU_SOURCE).

也就是说要定义__GNU_SOURCE或者在编译的时候加上-D  _GNU_SOURCE

注意#define __GNU_SOURCE要写在头文件之前

关于_GNU_SOURCE宏,发现它是在features.h中用于特性控制的一个功能测试宏

</user/include/features.h>

/* If _GNU_SOURCE was defined by the user, turn on all the other features.  */

#ifdef _GNU_SOURCE

# undef  _ISOC99_SOURCE

# define _ISOC99_SOURCE 1

# undef  _POSIX_SOURCE

# define _POSIX_SOURCE  1

# undef  _POSIX_C_SOURCE

# define _POSIX_C_SOURCE    200809L

# undef  _XOPEN_SOURCE

# define _XOPEN_SOURCE  700

# undef  _XOPEN_SOURCE_EXTENDED

# define _XOPEN_SOURCE_EXTENDED 1

# undef  _LARGEFILE64_SOURCE

# define _LARGEFILE64_SOURCE    1

# undef  _BSD_SOURCE

# define _BSD_SOURCE    1

# undef  _SVID_SOURCE

# define _SVID_SOURCE   1

# undef  _ATFILE_SOURCE

# define _ATFILE_SOURCE 1

#endif

 

其中_ISOC99_SOURCE, _POSIX_SOURCE, _XOPEN_SOURCE都是功能测试宏,用于指示是否包含对应标准的特性,而这些不同的特性源于过去20多年来进行的各种标准化工作(ANSI, ISO, POSIX, FIPS等),不同的标准支持实现了不同的特性,如系统时间的获取,stat结构是在ANSI标准中是不支持的,而定义了_GNU_SOURCE相当于开启了对所有特性的支持。


关于功能测试宏可以man  feature_test_macros

其中有几个功能测试宏是被默认定义的,如图

说明即使自己没定义功能测试宏,也会有一下功能测试宏被默认定义了


另外有几个man page 也有必要看一下

 man  libc
 man  syscalls
 man  standards


 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值