通过条件编译,实现C/C++项目的跨平台应用

 之前写过一篇文章,说明通过实现C/C++条件编译方式是实现水电站监控系统跨平台特性最合适的方式。这里我再补充说明其中的技术重点,其实也就是Unix/Linux与windows采用C/C++编程中需要注意的区别。

1. 文件访问相关函数

文件访问函数在不同的操作系统上存在一些行为细节方面的不同,如调用fread时候,windows上文件如果不用rb方式读取, 就会导致遇到空格的时候读取结束,而在Unix/Linux平台上不会出现。此外,在Unix/Linux上可以通过open函数打开文件后,通过read读取信息一般不会遇到问题,但在windows上采用相同调用方法,会发现明明文件中的内容还有很多read函数却没有按照调用入参中的长度限制返回最长的字符串,这可能是由于在windows上read函数中存在一个潜在的缓冲区限制。

2. IPC相关函数

IPC指的是Unix系统进程间访问,常用方式包括共享内存,消息队列和信号量。由于windows系统不支持这些功能,因此通过相近的功能替代。

2.1 共享内存

Unix上共享内存的调用方式基本如下:

​shm_id = shmget(SYS_DB_KEY, sizeof(SYS_DB)+i, 0666 | IPC_CREAT)
sysdb = (SYS_DB *)shmat(shm_id, (char *)0, 0)
​

但在windows上,不存在共享内存的机制,因此必须采用类似的技术代替,最简单的方式即文件映射内存,相同的代码段可以通过下面的方式修改:

sprintf(t_buf, "NCSYS_%d", SYS_DB_KEY);
HANDLE hFileMapping = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, sizeof(SYS_DB)+i, t_buf);
sysdb = MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);

2.2 消息队列

Unix环境下,消息队列的实现代码如下:

lan_msg_qid = msgget (LAN_CLIENT_MSG_KEY,0600)
msgsnd (lan_msg_qid,&init_msg,sizeof(init_msg),0))

由于windows上也不存在消息队列,因此采用其他技术实现,比如邮槽,上述代码可以通过下面的方式进行修改:

sprintf(servername, "\\\\.\\Mailslot\\%lld", LAN_CLIENT_MSG_KEY);  
lan_mailslot_handle = CreateFile(servername, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)
WriteFile(lan_mailslot_handle, &init_msg, sizeof(init_msg),&BytesWritten, NULL)

2.3 信号量

Unix下,信号量的实现代码如下:

1)	初始化:
    lan_semid = semget(LAN_SEM_KEY,1, 0600| IPC_CREAT | IPC_EXCL))
2)	P操作:
    structsembuf	sops[1];
    sops[0].sem_num = SEM_NUM;
    sops[0].sem_op = GET;
    sops[0].sem_flg = 0;
    semop(lan_semid, sops, 1)) 
3)	V操作:
    structsembuf	sops[1];
    sops[0].sem_num = SEM_NUM;
    sops[0].sem_op = RELEASE;
    sops[0].sem_flg = 0;
    semop(lan_semid, sops, 1)

信号量在windows操作系统中也存在,但是用法和含义与linux和Unix不同,这里按照windows信号量的用法改写代码,具体代码修改方式如下:

1)	初始化:
    lan_semid = CreateSemaphore(NULL, 0, 1, NULL);

2)	P操作:
    while(WaitForSingleObject(lan_semid,INFINITE) != WAIT_OBJECT_0);

3)	V操作:
    ReleaseSemaphore(lan_semid,1,NULL);

3. 网络访问

网络访问在windows操作系统中也存在,但是用法与linux和Unix不同,这里按照windows网络访问的用法改写代码。

 

  • 调用gethostbyname()等属于WinSock API库的函数前,必须要调用WSA-Startup函数,因此在所有程序执行前,直接增加WSA-Startup语句
  • 没有信号函数,所以不能使用sigset(SIGALRM, alarm_handler);通过alarm函数实现定时器功能。用event替代,代码如下:
DWORD    NumberOfBytesRead;
OVERLAPPED ov;
ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  • 没有gethostent,需要实现类似的代码。 
  • windows没有poll函数,使用windows完成端口代替。

4. 其他区别

  • 字节对齐方式不同,导致结构体的大小不同,需要在include定义中对结构体进行补字节的操作.
  • sleep函数不同参数不同,unix下sleep后面参数单位为秒,windows下Sleep函数参数单位为毫秒
  • windows不支持fork创建新进程,改成CreateProcess,并且需要增加一个exe来实现子进程行为,之前子进程的相关参数需要以参数方式带入子进程。
  • 没有gettimeofday,在windows平台上自行实现

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值