小编Mec*_*cki的帖子

套接字选项SO_REUSEADDR和SO_REUSEPORT,它们有何不同?它们在所有主要操作系统中的含义是否相同?

man pages和程序员单证套接字选项SO_REUSEADDR,并SO_REUSEPORT针对不同的操作系统,不同的,往往非常混乱.有些操作系统甚至没有选项SO_REUSEPORT.WEB中充满了关于此主题的矛盾信息,并且通常您可以找到仅对特定操作系统的一个套接字实现的信息,这些信息甚至可能在文本中没有明确提及.

那究竟有什么SO_REUSEADDR不同SO_REUSEPORT呢?

系统是否没有SO_REUSEPORT更多限制?

如果我在不同的操作系统上使用任何一个,那么预期的行为究竟是什么?

unix sockets linux windows portability

630
推荐指数
2
解决办法
24万
查看次数

递归锁定(互斥锁)与非递归锁定(互斥锁)

POSIX允许互斥锁递归.这意味着同一个线程可以锁定相同的互斥锁两次并且不会死锁.当然它还需要解锁两次,否则没有其他线程可以获得互斥锁.并非所有支持pthread的系统都支持递归互斥锁,但如果它们想要符合POSIX,则必须使用.

其他API(更高级别的API)通常也提供互斥锁,通常称为锁定.一些系统/语言(例如Cocoa Objective-C)提供递归和非递归互斥体.有些语言也只提供一种或另一种语言.例如,在Java中,互斥锁总是递归的(同一个线程可能在同一个对象上"同步"两次).根据它们提供的其他线程功能,没有递归互斥体可能没有问题,因为它们可以很容易地自己编写(我已经在更简单的互斥/条件操作的基础上自己实现了递归互斥锁).

我真的不明白:什么是非递归互斥量有用?如果它锁定相同的互斥锁两次,为什么我想要一个线程死锁?即使是可以避免这种情况的高级语言(例如测试它是否会死锁并抛出异常)通常也不会这样做.他们会让线程陷入僵局.

这只适用于我意外锁定它两次并且只解锁一次的情况,并且在递归互斥锁的情况下,它会更难找到问题,所以相反我立即死锁以查看错误锁定出现在哪里?但是我不能在解锁时返回一个锁定计数器并且在某种情况下,我确定我释放了最后一个锁并且计数器不为零,我可以抛出异常或记录问题吗?或者是否有其他更有用的非递归互斥体用例我看不到?或者它可能只是性能,因为非递归互斥体可能比递归互斥体略快?但是,我对此进行了测试,差异确实不大.

multithreading mutex deadlock locking recursive-mutex

176
推荐指数
6
解决办法
11万
查看次数

解决Objective-C命名空间冲突的最佳方法是什么?

Objective-C没有名称空间; 它很像C,一切都在一个全局命名空间内.通常的做法是使用首字母为类添加前缀,例如,如果您在IBM工作,则可以在前面加上"IBM"; 如果你在微软工作,你可以使用"MS"; 等等.有时首字母引用项目,例如Adium前缀带有"AI"的类(因为没有公司可以使用缩写).Apple使用NS作为前缀类,并说这个前缀仅供Apple使用.

到目前为止一切顺利.但是在前面添加2到4个字母到一个类名是一个非常非常有限的命名空间.例如,MS或AI可能具有完全不同的含义(例如,AI可能是人工智能),而其他一些开发人员可能决定使用它们并创建一个同名的类.Bang,命名空间冲突.

好吧,如果这是你自己的一个类和你正在使用的外部框架之间的冲突,你可以轻松地改变你的类的命名,没什么大不了的.但是如果你使用两个外部框架,那么你没有源代码的框架和你无法改变的框架呢?您的应用程序与它们都链接,并且您会收到名称冲突.你会如何解决这些问题?以这样的方式解决它们的最佳方法是什么,你仍然可以使用这两个类?

在C中,您可以通过不直接链接到库来解决这些问题,而是使用dlopen()在运行时加载库,然后使用dlsym()找到您要查找的符号并将其分配给全局符号(即可以任何你喜欢的方式命名)然后通过这个全局符号访问它.例如,如果您遇到冲突,因为某个C库有一个名为open()的函数,您可以定义一个名为myOpen的变量并让它指向库的open()函数,因此当您想要使用系统open()时,你只需使用open(),当你想使用另一个时,你可以通过myOpen标识符访问它.

在Objective-C中是否有类似的可能性,如果没有,是否还有其他聪明,棘手的解决方案可以使用解析命名空间冲突?有任何想法吗?


更新:

只是为了澄清这一点:建议如何提前避免命名空间冲突或如何创建更好的命名空间的答案当然是受欢迎的; 但是,我不会接受它们作为答案,因为它们不能解决我的问题.我有两个库和它们的类名冲突.我无法改变它们; 我没有任何一个的来源.碰撞已经存在,如何提前避免它的提示将不再有用.我可以将它们转发给这些框架的开发人员,并希望他们在未来选择更好的命名空间,但目前我正在寻找一个解决方案,以便在单个应用程序中使用框架.任何可能的解决方案?

macos cocoa namespaces objective-c

174
推荐指数
4
解决办法
4万
查看次数

SIGINT如何与其他终止信号相关?

在POSIX系统上,终止信号通常具有以下顺序(根据许多MAN页面和POSIX规范):

  1. SIGTERM - 礼貌地要求进程终止.它将正常终止,清理所有资源(文件,套接字,子进程等),删除临时文件等.

  2. SIGQUIT - 更有力的请求.它应该终止不正常,仍然清理绝对需要清理的资源,但可能不会删除临时文件,可能会在某处写入调试信息; 在某些系统上也会写入核心转储(无论信号是否被应用程序捕获).

  3. SIGKILL - 最有力的要求.甚至没有要求该过程做任何事情,但系统将清理过程,无论是否喜欢.最有可能是编写核心转储.

SIGINT如何适应这张照片?当用户点击CRTL + C时,CLI进程通常由SIGINT终止,但是后台进程也可以由SIGINT使用KILL实用程序终止.我在规范或头文件中看不到的是SIGINT是否比SIGTERM更强或更强,或者SIGINT和SIGTERM之间有任何区别.

更新:

到目前为止,我发现的终止信号的最佳描述是在GNU LibC文档中.它很好地解释了SIGTERM和SIGQUIT之间存在预期的区别.

它说关于SIGTERM:

这是礼貌地要求程序终止的正常方式.

它说关于SIGQUIT:

[...]并在终止进程时生成核心转储,就像程序错误信号一样.您可以将此视为用户"检测到"的程序错误情况.[...]在处理SIGQUIT时最好省略某些类型的清理.例如,如果程序创建临时文件,它应该通过删除临时文件来处理其他终止请求.但是SIGQUIT最好不要删除它们,以便用户可以与核心转储一起检查它们.

而SIGHUP也解释得很好.SIGHUP实际上不是终止信号,它只是意味着用户的"连接"已经丢失,因此应用程序不能指望用户读取任何进一步的输出(例如stdout/stderr输出),并且没有输入可以从用户不再.对于大多数意味着他们退出的应用程序.从理论上讲,应用程序还可以决定在收到SIGHUP时进入守护进程模式,现在作为后台进程运行,将输出写入已配置的日志文件.对于已经在后台运行的大多数守护进程,SIGHUP通常意味着他们将重新检查其配置文件,因此您在编辑配置文件后将其发送到后台进程.

但是,除了CRTL + C发送的SIGINT之外,此页面上没有有用的SIGINT解释.是否有理由以不同于SIGTERM的方式处理SIGINT?如果是这样,那将是什么原因以及如何处理不同?

unix linux posix

95
推荐指数
4
解决办法
5万
查看次数

我们如何恢复ppc/ppc64以及对Xcode 4的完整10.4/10.5 SDK支持?

由于Apple只发布带有Xcode4的SDK 10.6,因此用Xcode4开发PPC应用程序变得不可能.虽然可以使用Xcode4开发应用程序,也可以在10.5甚至10.4系统上运行(通过选择SDK 10.6,但部署目标10.5或10.4),但它们只能在Intel Mac上运行,因为您至少需要SDK 10.5才能运行构建PPC应用程序.

此外,还有一些罕见的情况,您需要在10.6之前构建一个SDK以获得完整的平台支持,例如,如果某些已弃用的功能已完全从10.6 SDK中消失,但您必须使用它并且动态链接不是在这些情况下总是最好的选择.同时链接早期的SDK有时会使开发变得简单,因为它会导致与早期操作系统版本不兼容,因为它会导致与早期操作系统版本不兼容,并且任何尝试使用它无论如何都会立即导致编译器或链接器错误.

最后但并非最不重要的是Apple还从Xcode4中移除了GCC 4.0支持,这可能是某些软件正确构建所必需的,Apple在使用SDK 10.4时从未允许使用GCC 4.2编译软件,尽管我几乎不相信这会导致任何问题,毕竟使用GCC 4.2和SDK 10.6构建的软件也可以在Mac OS 10.4上运行而没有任何问题,只要已正确设置部署目标并且没有使用MacOS 10.4下不可用的功能.

当然,你总是可以在Xcode4旁边并行安装Xcode3,但这意味着你必须放弃Xcode4的所有(伟大的?)新功能,并继续使用过时的Xcode3 IDE.如果您还可以在同一个IDE中管理所有旧项目,并且可以使用任何新功能,那肯定会好得多.并非所有项目都可以在可预见的将来制作10.6或英特尔.此外,我严格反对在早期实际需要之前取消对旧平台的支持.

我们可以将此功能恢复到Xcode4吗?

xcode osx-leopard powerpc universal-binary xcode4

93
推荐指数
3
解决办法
4万
查看次数

如果知道背景颜色,如何找到漂亮的字体颜色?

似乎有很多色轮,颜色选择器和颜色匹配器网络应用程序,在那里你给出一种颜色,他们会发现一些其他颜色,当组合使用时会产生谐波布局.但是,它们中的大多数仅关注背景颜色,并且在每种背景颜色上打印的任何文本(如果在预览中完全打印文本)是黑色或白色.

我的问题不同了.我知道我想用于文本区域的背景颜色.我需要帮助的是选择几种颜色(更多,更好,我可以在这个背景上用作字体颜色).最重要的是,颜色将确保字体是可读的(对比度不是太低,也可能不是太高,以避免眼睛受到压力),当然,前景和背景的组合看起来很好.

有人知道这样的申请吗?我更喜欢Web应用程序,我需要下载任何内容.谢谢.

accessibility readability colors

86
推荐指数
1
解决办法
14万
查看次数

为什么有一个单独的投影矩阵,同时结合模型和视图矩阵是有益的?

当您学习3D编程时,您会被教导从3个转换矩阵的角度来考虑它是最简单的:

  1. 模型矩阵.该矩阵对于每个模型都是独立的,它可以根据需要旋转和缩放对象,最后将其移动到3D世界中的最终位置."模型矩阵将模型坐标转换为世界坐标".

  2. 视图矩阵.对于大量对象(如果不是对于所有对象),该矩阵通常是相同的,并且它根据当前"摄像机位置"旋转并移动所有对象.如果您对相机拍摄3D场景进行成像,并且屏幕上呈现的内容是此相机捕获的图像,则相机的位置及其查看方向定义场景的哪些部分可见以及对象如何出现在捕获的图像上.在渲染单个帧时更改视图矩阵几乎没有理由,但实际上存在这些原因(例如,通过渲染场景两次并更改其间的视图矩阵,您可以在场景中创建一个非常简单但令人印象深刻的镜像) .通常,视图矩阵在绘制的两个帧之间仅改变一次."视图矩阵将世界坐标转换为眼睛坐标".

  3. 投影矩阵.投影矩阵决定这些3D坐标如何被映射到2D坐标,例如,如果存在应用于它们的透视(对象变得越小,它们离观察者越远)(正交投影).投影矩阵几乎没有变化.如果您渲染到窗口并且窗口大小已更改,或者您正在全屏渲染并且分辨率已更改,则可能必须更改,但是仅当新窗口大小/屏幕分辨率具有与之前不同的显示宽高比时.有一些疯狂的效果,你可能想要改变这个矩阵,但在大多数情况下,它对于整个程序的实时几乎是不变的."投影矩阵将眼睛坐标转换为屏幕坐标".

这对我来说很有意义.当然,总是可以将所有三个矩阵组合成单个矩阵,因为首先将矢量乘以矩阵A然后乘以矩阵B与将矢量乘以矩阵相同C,其中C = B * A.

现在,如果你看一下经典的OpenGL(OpenGL 1.x/2.x),OpenGL知道一个投影矩阵.然而,OpenGL不提供模型或视图矩阵,它只提供组合的模型视图矩阵.为什么?此设计强制您永久保存和恢复"视图矩阵",因为它将被应用于它的模型转换"破坏".为什么没有三个单独的矩阵?

如果你看一下新的OpenGL版本(OpenGL 3.x/4.x)并且你没有使用经典的渲染管道而是使用着色器(GLSL)自定义所有内容,那么根本就没有可用的矩阵,你必须定义自己的矩阵.大多数人仍然保留投影矩阵和模型视图矩阵的旧概念.为什么要这么做?为什么不使用三个矩阵,这意味着您不必永久保存和恢复模型视图矩阵,或者使用单个组合模型 - 视图 - 投影(MVP)矩阵,这可以节省顶点着色器中的矩阵乘法对于任何单个顶点渲染(毕竟这样的乘法也不是免费的).

因此,总结一下我的问题:在具有三个单独的矩阵或单个MVP矩阵的情况下,哪个优势具有组合的模型 - 视图矩阵以及单独的投影矩阵?

opengl glsl

48
推荐指数
1
解决办法
7094
查看次数

SVN:您是否可以从本地签出中删除目录(而不是从存储库中删除)?

假设您在subversion控件下有一个目录,其中包含一些文件和大量子目录,如下所示:

file1.txt
file2.txt
file3.txt
dir1/
dir2/
dir3/
dir4/
:
dirXX/
Run Code Online (Sandbox Code Playgroud)

现在你需要文件和一些目录,但不是全部.这可以通过SVN完成.只是使结账非递归:

svn checkout -N <URL>
Run Code Online (Sandbox Code Playgroud)

这只检出第一个目录和里面的文件.没有包含子目录.即使你进入checkout目录并运行" svn up",它只会更新之前检出的文件,它不会添加目录.您现在可以通过显式更新这些目录来有选择地添加所需的目录.例如,如果您只需要dir2和dir4,则可以进入结帐目录并执行

svn up dir2
svn up dir4
Run Code Online (Sandbox Code Playgroud)

如果您svn up将来运行通用" ",它将只更新文件和那两个目录,它不会添加任何其他目录.

现在的问题是:如果我以后再决定我不再需要dir2怎么办?我怎么摆脱它?似乎没有办法这样做,除了删除整个结帐并从头开始.

当你刚删除dir2时,下一个" svn up"将把它带回来,因为" svn status"当然显示它现在缺失("!"在它的名字前面).运行" svn remove"当然会将其删除,但在下一次提交时,它也会将其从存储库中删除,这不会发生.

即使是SVN 1.5的新稀疏目录("浅签出")功能也没用:

Subversion 1.5的浅层检查实现很好,但不支持一些有趣的行为.首先,您无法取消望远镜查看工作副本项目.在无限深度工作副本中运行svn update --set-depth empty将不会丢弃除最顶层目录之外的所有内容 - 它只会出错.
- http://svnbook.red-bean.com/en/1.5/svn.advanced.sparsedirs.html

这对SVN来说完全不可能吗?有没有人想出一个聪明的工作?

只需创建checkout目录(没有SVN),然后直接从存储库中检出单个子目录作为该目录的子目录将适用于目录:现在每个目录都是自己的结帐,可以更新,一旦不再需要,你可以删除它.但是,我如何获取文件(例如file1.txt)?SVN不允许签出单个文件,只能签出整个目录.

svn

47
推荐指数
3
解决办法
2万
查看次数

快速查找一组范围内一个数字范围的快速算法?

情景

我有几个数字范围.这些范围不重叠 - 因为它们不重叠,逻辑结果是任何时候任何数字都不能成为多个范围的一部分.每个范围都是连续的(单个范围内没有孔,所以8到16的范围实际上包含8到16之间的所有数字),但两个范围之间可能存在空洞(例如范围从64开始到128,下一个范围从256开始并转到384),因此某些数字可能根本不属于任何范围(在此示例中,数字129到255不属于任何范围).

问题

我得到一个号码,需要知道该号码属于哪个范围......如果它属于任何范围.否则我需要知道它不属于任何范围.当然速度很重要; 我不能简单地检查所有范围是O(n),因为可能有数千个范围.

简单解决方案

一个简单的解决方案是将所有数字保存在已排序的数组中并对其运行二进制搜索.这至少会给我O(log n).当然二进制搜索必须稍微修改,因为它必须始终检查范围的最小和最大数量.如果要查找的数字介于两者之间,我们找到了正确的范围,否则我们必须搜索当前范围之下或之上的范围.如果最后只剩下一个范围并且数字不在该范围内,则该数字根本不在范围内,我们可以返回"未找到"结果.

范围也可以在某种树形结构中链接在一起.这基本上就像是带有二分搜索的排序列表.优点是修改树比修改数组(添加/删除范围)更快,但不像我们浪费一些额外的时间来保持树平衡,树可能会在一段时间内变得非常不平衡,这将导致比排序数组上的二进制搜索慢得多.

人们可以争论哪种解决方案更好或更差,因为实际上搜索和修改操作的数量几乎是平衡的(每秒执行的搜索和添加/删除操作数量相同).

对于这类问题,是否有比排序列表或树更好的数据结构?也许在最好的情况下可能比O(log n)更好,在最坏的情况下可能比O(log n)更好?

此处可能有用的一些其他信息如下:所有范围始终以2的幂的倍数开始和结束.它们总是以相同的2的幂开始和结束(例如,它们以4的倍数或8的倍数或16的倍数开始/结束,依此类推).在运行时,2的功率不能改变.在添加第一个范围之前,必须设置2的幂,并且所有已添加的范围必须以此值的倍数开始/结束,直到应用程序终止.我认为这可以用于优化,好像它们都以例如8的倍数开始,我可以忽略所有比较操作的前3位,其他位将告诉我范围(如果有的话).

我读到了关于树和树的范围.这些是问题的最佳解决方案吗?有没有更好的解决方案?问题听起来类似于malloc实现必须做的事情(例如,每个freed内存块属于一系列可用内存,malloc实现必须找到哪一个),那么通常如何解决这个问题呢?

algorithm search range

37
推荐指数
3
解决办法
1万
查看次数

三色增量更新GC:是否需要扫描每个堆栈两次?

让我简单介绍一下三色GC(如果有人读到它,从未听说过它); 如果你不在乎,跳过它并跳转到问题.

三色GC的工作原理

在三色GC中,物体具有三种可能的颜色中的一种; 白色,灰色和黑色.三色GC可描述如下:

  1. 所有物体最初都是白色的.

  2. 由于全局变量或堆栈变量引用它("根对象"),所有可到达的对象都是灰色的.

  3. 我们采用任何灰色物体,找到它对白色物体的所有参考,并将这些白色物体着色为灰色.然后我们将对象本身涂成黑色.

  4. 只要我们有灰色物体,我们就在第3步继续.

  5. 如果我们不再有灰色物体,则所有剩余的物体都是白色或黑色.

  6. 所有黑色物体都被证明是可以到达的,必须保持活力.所有白色对象都无法访问,可以删除.

到目前为止,这并不是太复杂......至少如果GC是StW(停止世界),这意味着它会在收集垃圾时暂停所有线程.如果它是并发的,则三色GC具有必须始终保持为真的不变量:

黑色物体不得指白色物体!

这对于StW GC自动成立,因为之前已经检查过每个黑色的物体,并且它指向的所有白色物体都是灰色的,因此黑色物体可能仅指其他黑色物体或灰色物体.

如果线程没有暂停,线程可以执行会破坏此不变量的代码.有几种方法可以防止这种情况:

  1. 捕获对指针的所有读取访问权限,并查看是否对白色对象进行了读取访问.如果是,立即将对象的颜色变为灰色.如果现在将对此对象的引用分配给黑色对象,则无关紧要,该对象不再是灰色而不是白色(此实现使用读取屏障)

  2. 捕获对指针的所有写访问权,并查看指定的对象是否为白色,并且指定的对象是否为黑色.如果是这样,请将白色物体着色为灰色.这是更明显的做事方式,但也需要更多的处理时间(此实现使用写屏障)

由于读取访问比写入访问更常见,即使第二种可能性涉及更多的处理时间,当屏障被击中时,它被称为不那么频繁而且是受欢迎的.像这样工作的GC称为"增量更新GC".

这两种技术都有其他选择,称为SatB(起点时的快照).考虑到在任何时候都没有必要坚持不变量这一事实,这种变化略有不同,因为只要GC知道这个白色物体曾经是黑色物体是否引用白色物体并不重要并且在当前GC循环期间仍然可以访问(或者因为仍然有灰色对象引用此白色对象,或者因为此白色对象的引用被放置到GC运行时也考虑的显式堆栈上用灰色物体).SatB收藏家在实践中更常使用,因为它们有一些优点,但恕我直言,它们更难实施.

我在这里指的是增量更新GC,它使用变量2:每当代码试图使黑色物体指向白色物体时,它立即将物体灰色着色.这样,在收集周期中不会错过这个对象.

问题

关于三色GC的问题非常多.但有一点我不了解三色GC.假设我们有一个对象A,它由栈引用,它本身引用一个对象B.

stack -> A.ref -> B
Run Code Online (Sandbox Code Playgroud)

现在GC启动一个循环,停止线程,扫描堆栈并将A视为可直接访问,着色为灰色.一旦完成扫描整个堆栈,它再次取消线程并在步骤(3)开始处理.在它开始执行任何操作之前,它被抢占(可能发生)并且线程再次运行并执行以下代码:

localRef = A.ref; // localRef points to B
A.ref = NULL;     // Now only the stack points to B
sleep(10000);     // Sleep for the whole GC cycle
Run Code Online (Sandbox Code Playgroud)

由于没有违反不变量,B是白色的,但是没有被分配给黑色物体,B的颜色没有变化,它仍然是白色的.A不再引用B,因此在处理"灰色"A时,B不会改变其颜色,A将变为黑色.在周期结束时,B仍然是白色的,看起来像垃圾.但是,localRef指的是B,因此它不是垃圾.

问题

我是对的,三色GC必须扫描每个线程的堆栈两次吗?一旦开始,识别根对象(变为灰色)并在删除白色对象之前再次识别,因为堆栈可能会引用这些对象,即使没有其他对象再引用它们.到目前为止,我没有看到过关于扫描堆栈两次的任何关于算法的描述.他们都只是说,当使用并发时,重要的是始终强制执行不变量,否则会丢失可达对象.但据我所知,这还不够.必须将堆栈视为单个大对象,并且一旦扫描,"堆栈为黑色",堆栈的每次ref更新都必须使对象变为灰色.

如果确实如此,使用增量更新可能比我最初想象的更棘手,并且有一些性能缺陷,因为堆栈更改是最常见的.

language-agnostic garbage-collection

28
推荐指数
2
解决办法
4575
查看次数