Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

Cygwin知识集锦

13
Jul
2010

Cygwin知识集锦

By Alex
/ in C,C++
/ tags Cygwin, FAQ, Porting
0 Comments
基本知识
Cygwin简介

Cygwin是一个用于Windows操作系统下的类Linux环境。包括以下组件:

  1. cygwin1.dll:一个提供大量POSIX系统调用功能的模拟层,位于Cygwin程序与Windows操作系统之间。目前有32/64位版本支持Windows XP3之后的所有NT系统。cygwin1.dll提供的API尽可能的遵守UNIX规范、Linux实践。与Linux不同,Cygwin使用的C标准库是newlib而不是glibc
  2. 一系列的工具集,提供类似Linux的行为,例如命令、类库等

当第一个基于Cygwin的进程创建时,cygwin1.dll被加载到其代码段,并创建共享内存区域、全局同步对象。这些区域和对象被所有Cygwin进程共享(虽然他们有各自的cygwin1.dll实例),可以用于跟踪打开的文件描述符,以及辅助fork、exec调用。每个Cygwin进程具有包含PID、UID、信号掩码的进程结构。

Cygwin与MinGW

Cygwin与MinGW虽然都会被作为GNU工具链看待,但是二者在本质上是不同的。

Cygwin在某种程度上可以看作一个虚拟的操作系统层(如上所述,由cygwin1.dll驱动),在其上运行的应用程序可以使用绝大部分POSIX接口,这些程序感觉自己就在Linux上运行一样。

MinGW虽然也提供了POSIX风格的接口,但是这些接口的实现都是被对接到Win32 API上的。MinGW编译的程序是纯粹的Win32应用程序,因此也无法支持一些Linux下特有的系统调用,例如fork()。

Cygwin与虚拟机

Windows下的Linux虚拟机可以直接运行Linux应用程序,而Cygwin则不能运行,程序必须从源代码重新编译。Cygwin程序是标准的Windows PE格式。

不兼容性

由于Windows本身的限制,Cygwin无法保持POSIX兼容性,但是这样的情况比较少见。

Cygwin提供的POSIX兼容性和Windows API并非水乳交融,因此如果在应用中混用POSIX调用、Windows调用,可能导致意外结果。特别的,Cygwin信号与阻塞的Windows函数不能一起使用。

文件与权限

Cygwin同时支持POSIX、Win32风格的路径。传递给DLL的路径被转换为Win32格式;在Cygwin应用看来,文件系统是POSIX兼容的。

从1.7.0开始,/etc/fstab中包含了Windows文件系统到POSIX文件系统的映射关系。如果不进行默认设置,将进行类似这样的映射: C:\Windows -> /cygdrive/c/Windows   

Windows NT包含了一个基于ACL的安全模型。在支持此ACL的文件系统(NTFS)上,Cygwin将Win32文件所有权、权限映射到ACL。chmod调用将UNIX文件权限映射到Win32等价的权限上。

具有管理员权限的用户可以chown文件所有者。

Cygwin 1.1.3引入了设置Real UID、Effective UID的机制。

进程创建

Cygwin中的fork调用没有很好的映射到Win32 API上。fork()调用本身的语义要求父子进程的地址空间布局完全一致,而Windows本身没有提供在进程间拷贝地址空间的机制,此外Windows下的一些特性可能破坏fork()实现的可靠性,这导致了一些流行问题:

  1. DLL基址冲突:与类UNIX系统使用“位置无关代码”的共享库不同,Windows共享库假设了一个固定的基址。一旦同一个进程加载的两个DLL的基址冲突了,Windows就要将其中一个“rebase”到不同的地址上,这种rebase行为具有不一致性:可能每次rebase的DLL不同,移动到的目的位置也不同。Cygwin可以为动态加载的DLL补充前述的不一致性。但是对于静态链接的DLL(statically-linked)之间的冲突,是在cygwin.dll加载之前就被Windows处理的,Cygwin无能为力,只能通过rebaseall工具处理
  2. Windows Vista开始引入的地址空间布局随机化(ASLR),允许线程栈、堆、内存映射文件、静态链接DLL随机的定位到进程的地址空间。此行为会干涉fork()的正常行为。如果不可移动对象(进程堆、系统DLL)被定位在错误的位置,Cygwin无法进行补偿行为

总之,现有的Windows实现导致无法实现完全可靠的fork(),偶发性的fork()失败不可避免。

信号

当Cygwin进程启动后,会有一个辅助线程被用于信号的处理,该线程等待Windows事件,并将其转换为信号,当进程收到信号后,会根据信号bitmask的设置进行合适的处理。大部分的UNIX信号被支持。

套接字

在Cygwin中与Socket相关的调用基本上是调用了Winsock的对应物——MS的Berkeley Socket实现,但是使用了一些技巧。例如,为了允许POSIX信号来中断阻塞调用,所有的Socket调用在底层都是非阻塞的。

由于地址族AF_UNIX在Winsock下不可用,Cygwin利用本地AF_INET代替之,但是这对程序是透明的。

select

UNIX的select()函数也不能清晰的映射到Win32 API。在Windows下,select()只能用于套接字的处理,而UNIX下可以用于各种类型的文件描述符。

安装与配置

下载setup-x86.exe到安装目录,例如D:\CPP\tools\Cygwin,双击即可安装,设置好安装目录、下载目录后,选择163的镜像即可安装。Cygwin会显示已经port的软件包的列表,根据需要安装即可。

如果想安装基于AMD64的cygwin,可以下载setup-x86_64.exe,但是64位的Cygwin中,类库和工具没有32位的全面。

常用的软件包
软件包  说明 
apt-cyg 安装此软件后,不需要每次都打开setup-x86.exe进行软件安装,只需要使用类似于apt-get方式即可安装:
Shell
1
2
3
4
wget http://apt-cyg.googlecode.com/svn/trunk/apt-cyg
chmod +x apt-cyg mv apt-cyg /usr/local/bin/
#切换源
apt-cyg update -m http://mirrors.163.com/cygwin

注:目前Cygwin已经修改了散列算法,对于apt-cyg 0.95,应该修改343行的md5sum为sha512sum

ncurses  与Terminal使用相关的小工具,例如clear命令
cygserver 该工具自动安装,需要运行 /usr/bin/cygserver-config进行必要的配置。cygserver用于支持以“服务”默认来运行Cygwin应用程序。配置步骤如下:
Shell
1
2
3
4
5
6
#下载需要的软件
apt-cyg install cygrunsrv
#只需配置,会依次提示:
#... /etc/cygserver.conf file?  yes
#install cygserver as service?  yes
/usr/bin/cygserver-config

完毕后,在Windows系统服务中可以看到一个“CYGWIN cygserver”,启动即可。

Devel目录 开发人员必备的软件包都在该目录下,对于C/C++开发,需要AutoTools(autoconf、automake)、binutils、cmake、cygwin-devl、gcc-core、gcc-g++、gdb、libtool、make
Cygwin/X 在Cygwin下运行基于X Windows的GUI应用,例如gedit,需要用到,安装步骤:
Shell
1
2
3
4
5
6
7
8
apt-cyg install xorg-server xinit xorg-docs X-start-menu-icons
#通过下面的命令可以在多窗口模式下启动一个X server,并且附加一个X terminal
/usr/bin/startxwin
#可以安装桌面管理器,例如:
apt-cyg install mate-session-manager
#安装完上面的MATE后,会发现字体渲染的比较粗糙,可以选用Apple LiHei、XCross_Mono.Clear分别
#作为一般字体、等宽字体(字体文件存至~/.fonts),并通过
#System - Preferences - Appearance -fonts 设置渲染方式为Subpixel Smoothing
OpenSSH 安装头SSH服务要求cygserver被安装。步骤如下:
Shell
1
2
3
4
5
6
7
8
9
10
apt-cyg install openssl openssh
ssh-host-config
#根据提示进行操作:
#if privilege separation should be used 选择no
#if sshd should be installed as a service 选择yes
#其余选择no
#完毕后,会多出一个NT服务,可以按如下方式启动之:
#net start "CYGWIN sshd"
#或者:
#cygrunsrv --start sshd

 默认的用户密码就是当前Windows的用户密码

输入法

在Cygwin/X下使用输入法,推荐ibus-pinyin,需要安装的包包括:ibus、ibus-pinyin、dconf(不安装的话配置无法生效)。

安装完毕后,设置ibus为自动启动(以MATE为例:System - Perferences - Startup Applications 添加“/usr/bin/ibus-daemon -d”)

Cygwin下的编程

在Cygwin下使用gcc,与在Linux下的用法一样,下面是编译、运行HelloWorld的例子:

Shell
1
2
3
gcc hello.c -o hello.exe  #注意后缀
hello.exe
#打印:Hello, World
构建64位应用程序

64位的Cygwin工具链默认使用微软x64调用协定。可以使用32位的Cygwin工具链、Win32 API来构建应用程序。

有一点需要注意的,64位Cygwin使用了和Windows、MinGW编译器不同的数据模型。后两者使用LLP64模型,而Cygwin使用与Linux一致的LP64模型。这两个模型一个重要区别是,前者的 sizeof(long) == 4 而后者的 sizeof(long) == 8 (与指针类型、size_t、ssize_t长度一致),该区别会对包括LONG, ULONG, DWORD在内的Win32类型用法产生影响。你不能假设DWORD与ssize_t的长度是一致的4字节整数。

构建GUI应用

Cygwin内置了X Server,因此可以把GUI英语编译为X applications。此外Cygwin允许你完整的使用Windows的GUI函数。构建GUI应用与命令行应用没有什么区别,只需要添加一个选项: gcc -mwindows 。

构建和使用DLL

DLL即动态链接库,其代码在运行期间动态的链接到应用程序,而不是在编译期间就静态的链接。DLL包括三个组成部分:

  1. 导出(exports ):包含了DLL允许外部访问的函数、变量的列表,其他部分对外隐藏
  2. 数据和代码:是DLL作者编写的部分,包括函数、变量,被合并为一整个的目标文件
  3. 导入库(import library):形式上与UNIX常规的*.a库一样,但是其中仅仅包含了很少的信息,用于告知OS,你的应用程序如何去“导入”DLL,该文件被链接到应用程序

基于最新版本的gcc和binutils,构建一个DLL的过程相当简单,下面是一个例子:

hello.c
C
1
2
3
4
5
6
#include
 
int hello()
{
    printf("Hello World!\n");
}
首先编译出目标代码(Object code): gcc -c hello.c 
然后,告诉gcc你希望构建一个共享库: gcc -shared -o hello.dll hello.o 
要使用这个共享库,只需要在你的代码中直接调用hello(),并使用类似下面的命令链接:  gcc -o SayHello SayHello.c -L./ -lhello 

 实际应用中,你可能需要更复杂的命令来构建DLL,例如:

Shell
1
2
3
4
5
6
7
8
9
10
11
#共享库的名字为module,前缀cyg用来将其与Native的Windows DLL区分
gcc -shared -o cyg${module}.dll
#libmodule.dll.a为用于导入的库stub
  -Wl,--out-implib=lib${module}.dll.a
#导出所有变量、函数
  -Wl,--export-all-symbols
  -Wl,--enable-auto-import
#需要整个捆绑到DLL中的目标文件、静态库
  -Wl,--whole-archive ${old_libs}
#该DLL需要与之链接的DLL的导入库
  -Wl,--no-whole-archive ${dependency_libs}
使用已有的DLL

如果要在Cygwin中使用已有的DLL,则需要生成Cygwin兼容的导入库,下面是一个示例:

Shell
1
2
3
4
5
echo EXPORTS > hello.def
#列出DLL中的符号,将其输出到文件
nm foo.dll | grep ' T _' | sed 's/.* T _//' >> hello.def
#生成导入库
dlltool --def hello.def --dllname hello.dll --output-lib hello.a
常见问题
Eclipse CDT无法识别工具链:Toolchain "Cygwin GCC" is not detected

可能是环境变量配置错误,必须在PATH中包含 %CYGWIN_HOME%\bin Eclipse CDT才能识别成功。

← 不变模式
基于Eclipse CDT的wxWidgets开发环境搭建 →

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

  • MinGW知识集锦
  • Windows下基于Eclipse CDT的C/C++开发
  • NaCl学习笔记
  • PHP知识集锦
  • Ubuntu知识集锦

Recent Posts

  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
  • A Comprehensive Study of Kotlin for Java Developers
  • 背诵营笔记
  • 利用LangChain和语言模型交互
  • 享学营笔记
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注容器方向。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
    In this blog post, I will walk ...
  • A Comprehensive Study of Kotlin for Java Developers
    Introduction Purpose of the Study Understanding the Mo ...
  • 背诵营笔记
    Day 1 Find Your Greatness 原文 Greatness. It’s just ...
  • 利用LangChain和语言模型交互
    LangChain是什么 从名字上可以看出来,LangChain可以用来构建自然语言处理能力的链条。它是一个库 ...
  • 享学营笔记
    Unit 1 At home Lesson 1 In the ...
  • K8S集群跨云迁移
    要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题: 各种K8S资源的迁移 工作负载所挂载的数 ...
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 90 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • Bazel学习笔记 37 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • Ceph学习笔记 27 people like this
  • 基于Calico的CNI 27 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • qg on Istio中的透明代理问题
  • heao on 基于本地gRPC的Go插件系统
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • haolipeng on 基于本地gRPC的Go插件系统
  • 吴杰 on 基于C/C++的WebSocket库
©2005-2025 Gmem.cc | Powered by WordPress | 京ICP备18007345号-2