﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-cyt</title><link>http://www.cppblog.com/cyt/</link><description /><language>zh-cn</language><lastBuildDate>Sat, 04 Apr 2026 00:40:01 GMT</lastBuildDate><pubDate>Sat, 04 Apr 2026 00:40:01 GMT</pubDate><ttl>60</ttl><item><title>如何在windows service里面控制console程序退出</title><link>http://www.cppblog.com/cyt/archive/2008/01/08/40723.html</link><dc:creator>cyt</dc:creator><author>cyt</author><pubDate>Tue, 08 Jan 2008 08:07:00 GMT</pubDate><guid>http://www.cppblog.com/cyt/archive/2008/01/08/40723.html</guid><wfw:comment>http://www.cppblog.com/cyt/comments/40723.html</wfw:comment><comments>http://www.cppblog.com/cyt/archive/2008/01/08/40723.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/cyt/comments/commentRss/40723.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyt/services/trackbacks/40723.html</trackback:ping><description><![CDATA[首先，要控制windows services，是比较容易的事情，一堆现成的例子。<br><a href="http://www.codeproject.com/KB/system/xyntservice.aspx">SYNtService</a> 就是一个很好的例子。<br>要控制一个窗口退出是十分容易的事情，PostMessage就可以解决问题。<br>要控制console退出，也有很多现成的方法。比较通用的方法：<br>1、TerminateProcess<br>&nbsp;&nbsp; 最原始、最暴力的强制console退出的方法。console进程毫无还手之力就over了。但我希望console在推出之前至少能处理一下&#8220;后事&#8221;。<br><br>2、signal / raise<br>&nbsp;&nbsp; 原来windows也有signal，不过kill换成了raise。但是相对Unix系列的signal功能就差很远了。而且有一个麻烦的地方就是raise只能对本console生效，而不能对指定的process。<br>&nbsp;&nbsp; 可以在signal里面指定一个call back函数，在收到SIGINT/SIGTERM之类的时候，处理一下事情，然后通知各个线程结束。<br>&nbsp;&nbsp; 既然不能raise其他进程，是否这个功能就不能用了呢？其实可以考虑一下CreateRemoteThread，然后在别人的进程里面raise&#8230;&#8230;<br><br>3、SetConsoleCtrlHandler / GenerateConsoleCtrlEvent<br>&nbsp;&nbsp;&nbsp; 这个是console专门用来处理Ctrl-C/Ctrl-Break/以及windows关机事件等的处理方法。比signal更强大。而且说明中写了，可以对其他的进程进行处理（还可以对进程组处理）。用网上的话说就是：很女子，很弓虽！<br>&nbsp;&nbsp;&nbsp; 但是要注意，如果要对其创建的子进程进行处理的时候，创建子进程必须要使用CREATE_NEW_PROCESS_GROUP标志。另外一点，文档写的比较隐晦的就是，进程必须要有console窗口。否则，调用GenerateConsoleCtrlEvent会返回6，说ERROR_INVALID_HANDLE。<br>&nbsp;&nbsp;&nbsp; 问题来了，Service本身是没有console窗口的，Service建立的子进程就必须要自带窗口了。但是一般为了美观，Service启动的进程都不想带有窗口。那就变成了子进程没有console窗口，GenerateConsoleCtrlEvent失效了。<br>&nbsp;&nbsp;&nbsp; 在网上查了很多资料（怎么没看到很黄很暴力呢？？？），其中在<strong><span class="FakeLink" onclick="window.location=getMailto();" onmouseover="window.status='Click to send e-mail.';" onmouseout="window.status='';">
</span></strong><span class="FakeLink" onclick="window.location=getMailto();" onmouseover="window.status='Click to send e-mail.';" onmouseout="window.status='';">Louis K. Thomas
&lt;loui<span style="display: none;">N&#216;SP@M</span>sth@hotm<span style="display: none;">&#209;OSP@M</span>ail.co<span style="display: none;">N&#213;SP@M</span>m&gt; 的</span> <a href="http://www.latenighthacking.com/projects/2003/sendSignal/">SendSignal</a><span style="text-decoration: underline;"></span> 提到一种做法，就是先获得kernel32!CtrlRoutine的入口，然后通过CreateRemoteThread的方法，让远程的console来执行kernel32!CtrlRoutine。但这种方法有个问题，在获得kernel32!CtrlRoutine的时候，也是使用GenerateConsoleCtrlEvent来获得。但是Service自己本身没有console窗口，一调用GenerateConsoleCtrlEvent也是出错。<br>而另一篇 <a  href="http://groups.google.com/group/microsoft.public.win32.programmer.kernel/browse_thread/thread/a705105bc415a409/a5d6a5161fcb7450?hl=en&amp;lnk=st&amp;q=GenerateConsoleCtrlEvent+++ERROR_INVALID_HANDLE#a5d6a5161fcb7450">google讨论组</a> 文章，里面提到原来可以先AllocConsole、然后GenerateConsoleCtrlEvent、然后FreeConsole&#8230;&#8230;于是解决方案就变成：<br>Service里面:<br>&nbsp; 先AllocConsole<br>&nbsp; 然后利用GenerateConsoleCtrlEvent获得kernel32!CtrlRoutine<br>&nbsp; 然后FreeConsole<br>&nbsp; 当需要结束进程的时候，就调用CreateRemoteThread，把kernel32!CtrlRoutine的代码注入到子process中执行<br>&nbsp; 这样大家都看不到console窗口（service里面AllocConsole很快，看不到窗口出来，甚至怀疑根本就有没有窗口出来），同时又能通知子进程优雅地退出。<br><br>存在问题：如果我的机器作为服务器启动，即没有进入登录状态，不知道这样启动的Service会不会有问题呢？？暂时还没有时间测试。<br><br><br>&nbsp;&nbsp;&nbsp; <br><span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; <br></span><strong style="color: black; background-color: #a0ffff;"></strong><br> <img src ="http://www.cppblog.com/cyt/aggbug/40723.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyt/" target="_blank">cyt</a> 2008-01-08 16:07 <a href="http://www.cppblog.com/cyt/archive/2008/01/08/40723.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>中秋节快乐</title><link>http://www.cppblog.com/cyt/archive/2007/09/25/32837.html</link><dc:creator>cyt</dc:creator><author>cyt</author><pubDate>Tue, 25 Sep 2007 04:16:00 GMT</pubDate><guid>http://www.cppblog.com/cyt/archive/2007/09/25/32837.html</guid><wfw:comment>http://www.cppblog.com/cyt/comments/32837.html</wfw:comment><comments>http://www.cppblog.com/cyt/archive/2007/09/25/32837.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/cyt/comments/commentRss/32837.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyt/services/trackbacks/32837.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 中秋节快乐！<br>介绍了一本书和几个C++lib&nbsp;&nbsp;<a href='http://www.cppblog.com/cyt/archive/2007/09/25/32837.html'>阅读全文</a><img src ="http://www.cppblog.com/cyt/aggbug/32837.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyt/" target="_blank">cyt</a> 2007-09-25 12:16 <a href="http://www.cppblog.com/cyt/archive/2007/09/25/32837.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>补充一个OCI的问题</title><link>http://www.cppblog.com/cyt/archive/2007/03/30/20912.html</link><dc:creator>cyt</dc:creator><author>cyt</author><pubDate>Thu, 29 Mar 2007 16:00:00 GMT</pubDate><guid>http://www.cppblog.com/cyt/archive/2007/03/30/20912.html</guid><wfw:comment>http://www.cppblog.com/cyt/comments/20912.html</wfw:comment><comments>http://www.cppblog.com/cyt/archive/2007/03/30/20912.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/cyt/comments/commentRss/20912.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyt/services/trackbacks/20912.html</trackback:ping><description><![CDATA[
		<p>前几天客户投诉我们提供的一个访问Oracle的程序，说运行太慢了，半天都没有处理完数据。<br />客户数据也就几十万条，也不是什么海量数据，究竟什么原因呢。而且奇怪的是我们提供的其它类似的程序访问同一张数据表却没有任何的问题。<br />经过多次反复写测试程序，尝试各种的条件，最后发现原来是其中一条update语句执行很慢，要2秒钟才更新一条。而这条update语句的where部分有两个条件，一个是整数的比较条件，一个是日期的比较条件。当然很容易就可以通过测试排除了整数条件导致慢的可能性。剩下的原因就是日期比较条件导致慢了。<br />说得也奇怪，日期条件是通过param的方式传入参数的，执行很慢。但测试的时候如果把日期条件展开，把日期条件变成SQL的一部分，那就执行很快了。先不论为什么这么奇怪，要知道Oracle SQL语句的日期条件不是一般的麻烦，都要经过TO_DATE/TO_CHAR糊弄来糊弄去，SQL语句跟其他的数据库不一样，程序就失去通用性了。一定是自己调用OCI的时候犯了什么糊涂错误了。<br />最后还是发现有一个不妥当的地方：数据库字段类型是DATE，而我用OCI绑定param的时候，用的却是SQLT_TIMESTAMP。原因是我想偷懒，希望用OraDateStruct就解决OCI的日期类型。于是我尝试用回SQLT_DAT，自己“笨笨的”把时间转换为OCI所能辨认的7个byte的数组，然后运行程序。速度太快了，一下子就执行完了。<br />其实不明白的是，Oracle发现类型不匹配，要不就报错；要不就把条件变为相容的数据进行查询。但是现在从现象看来，Oracle像是把所有保存的数据逐个转换成为与条件相容的类型进行判断，而不是转换条件的类型。所以每次update都变成了遍历所有的数据。难道是存在DBA可以调整的优化策略？？不明白，不明白……</p>
<img src ="http://www.cppblog.com/cyt/aggbug/20912.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyt/" target="_blank">cyt</a> 2007-03-30 00:00 <a href="http://www.cppblog.com/cyt/archive/2007/03/30/20912.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OpenDBX 一个访问多数据库的C类库</title><link>http://www.cppblog.com/cyt/archive/2007/03/29/20908.html</link><dc:creator>cyt</dc:creator><author>cyt</author><pubDate>Thu, 29 Mar 2007 15:31:00 GMT</pubDate><guid>http://www.cppblog.com/cyt/archive/2007/03/29/20908.html</guid><wfw:comment>http://www.cppblog.com/cyt/comments/20908.html</wfw:comment><comments>http://www.cppblog.com/cyt/archive/2007/03/29/20908.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cyt/comments/commentRss/20908.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyt/services/trackbacks/20908.html</trackback:ping><description><![CDATA[
		<a href="http://www.linuxnetworks.de/opendbx/">http://www.linuxnetworks.de/opendbx/</a>
		<br />
		<br />OpenDBX，一个开源的、简单的、可以访问多种数据库的C类库。按作者说的，已经支持：<br /><ul><li>Firebird</li><li>Interbase</li><li>MS SQL Server</li><li>MySQL</li><li>Oracle</li><li>PostgreSQL</li><li>SQLite</li><li>SQLite3</li><li>Sybase</li></ul>而且好像是使用动态载入模块方式，即dlopen打开相应驱动模块的so的方式，是有点ODBC的味道。<br />不过支持的数据类型以及SQL查询的功能有限。<br />留着以后可能会有些参考价值。<img src ="http://www.cppblog.com/cyt/aggbug/20908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyt/" target="_blank">cyt</a> 2007-03-29 23:31 <a href="http://www.cppblog.com/cyt/archive/2007/03/29/20908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>移植代码到64bits碰上的问题</title><link>http://www.cppblog.com/cyt/archive/2007/03/29/20907.html</link><dc:creator>cyt</dc:creator><author>cyt</author><pubDate>Thu, 29 Mar 2007 15:15:00 GMT</pubDate><guid>http://www.cppblog.com/cyt/archive/2007/03/29/20907.html</guid><wfw:comment>http://www.cppblog.com/cyt/comments/20907.html</wfw:comment><comments>http://www.cppblog.com/cyt/archive/2007/03/29/20907.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cyt/comments/commentRss/20907.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyt/services/trackbacks/20907.html</trackback:ping><description><![CDATA[
		<p>一晃眼，原来又有好几个月没有上来。其间写了几个月的javascript，写了几个月的JSP，C++的东西都没有怎么碰过了。<br /><br />这几天要原来项目的C++代码从32bit的平台移植到64bit的平台。由于以前编写类库的时候已经十分小心，也早有预谋，所以竟然很顺利的全部编译通过，而且-Wall下面都没有任何warning。满心欢喜之下运行了程序。谁知道马上就是一个Segment faul。沮丧之余用gdb跟踪了半天都不知道什么地方的问题。加上valgrind，也是一头雾水，竟然是说标准STL的hash_map的问题……最后在一次跟踪的时候，无意中检查一个指针的初始化值，发现不为空，原因应该就在这里。<br />翻查代码的上下文，原来指针是跟一个int放在同一个union当中，而union的初始化只初始化了int，而没有初始化指针。在64bit机器的gcc下，int是32bit而指针是64bit，所以就导致指针不为空的现象。所以赶紧把代码中所有union的地方都找出来检查一遍。幸好union这种东西平时不敢多用，也没发现其他的异常。程序重新编译，再运行，没有Segment fault了。<br /><br />然后再运行了一批unit test。发现其中有几个不能通过，其原因其实也是比较无聊。都是自己不小心之过：<br />1、sha1的代码copy php的，其中一个php_uint32变量竟然自己写了unigned long，傻瓜致极<br />2、有个地方保存各种长度整数到文件，因为偷懒，把函数写成了模板，大概就是：<br />   template&lt;typename typeInt&gt;<br />      int write(typeInt n) {<br />         writeToFile( &amp;n, sizeof(n));<br />      }<br />   然后一个不小心，想写个string的长度的时候就变成了：  write( str.length() );<br />   str.length()类型是size_t，64bit，与32bit系统的不一样，当然也就出错了。<br />   其实平时都已经很小心，尽量使用static_cast强制转换为特定长度类型的变量再输出的了，偏偏就是漏了一两个地方。</p>
<img src ="http://www.cppblog.com/cyt/aggbug/20907.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyt/" target="_blank">cyt</a> 2007-03-29 23:15 <a href="http://www.cppblog.com/cyt/archive/2007/03/29/20907.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>db4o and GigaBase</title><link>http://www.cppblog.com/cyt/archive/2006/11/17/15303.html</link><dc:creator>cyt</dc:creator><author>cyt</author><pubDate>Fri, 17 Nov 2006 09:11:00 GMT</pubDate><guid>http://www.cppblog.com/cyt/archive/2006/11/17/15303.html</guid><wfw:comment>http://www.cppblog.com/cyt/comments/15303.html</wfw:comment><comments>http://www.cppblog.com/cyt/archive/2006/11/17/15303.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cyt/comments/commentRss/15303.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyt/services/trackbacks/15303.html</trackback:ping><description><![CDATA[    昨晚参加了<a class="" title="db4o" href="http://www.db4o.com/china/Default.aspx?src=cn&amp;AspxAutoDetectCookieSupport=1" target="_blank">db4o</a>的RoadShow，终于见到英俊潇洒玉树临风，传说中的Matrix群主<span style="COLOR: red">Chris <img height="20" src="http://www.cppblog.com/Emoticons/QQ/laf.gif" width="20" border="0" /><br /><font color="#000000">    db4o给我的印象就是不依赖关系数据库的“Hibernate”，完全就是全自动对象序列化 + 超强查询。按照官方给出的数据，其嵌入式的应用环境下性能真的是无出其右了。但按我的理解，由于没有低粒度锁，必然存在无法解决的并发冲突，或者并发读问题不大，并发更改性能应该会有影响。究竟用了什么超强技术那就不知道，或者有空找来研究一下。个人感觉db4o并不是要用来替代数据库，而是数据保存的一个辅助。十分适合用于Cache系统或者应用于嵌入式设备。db4o只提供Java和C#接口，对于目前PDA应用来说似乎要求高了点。就如Rayman所说，解决了CPU和内存问题还有一个电源问题估计PDA近期也无法解决。<span style="COLOR: red">Christof<font color="#000000">一再强调其三段式事务保证数据文件完整；快速易用的开发模式；超大规模数据的支持……至于他们公司的开源盈利模式，小弟英文水平有限，听不懂了。<br />    很久以前就提到过<a class="" title="GigaBase" href="http://www.garret.ru/~knizhnik/gigabase.html" target="_blank">GigaBase</a>，似乎就是db4o的C++版本。不过C++先天不足，缺少反射机制，实现当然不能像db4o般优美了。但似乎这个选择也不错，可以告别BerkeleyDB、sqlit……从此步入OO数据保存的“天堂”……</font></span></font></span><img src ="http://www.cppblog.com/cyt/aggbug/15303.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyt/" target="_blank">cyt</a> 2006-11-17 17:11 <a href="http://www.cppblog.com/cyt/archive/2006/11/17/15303.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实在惭愧</title><link>http://www.cppblog.com/cyt/archive/2006/11/12/15090.html</link><dc:creator>cyt</dc:creator><author>cyt</author><pubDate>Sun, 12 Nov 2006 09:45:00 GMT</pubDate><guid>http://www.cppblog.com/cyt/archive/2006/11/12/15090.html</guid><wfw:comment>http://www.cppblog.com/cyt/comments/15090.html</wfw:comment><comments>http://www.cppblog.com/cyt/archive/2006/11/12/15090.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/cyt/comments/commentRss/15090.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyt/services/trackbacks/15090.html</trackback:ping><description><![CDATA[转眼原来自己已经大半年没有上来写log，同时也发现原来大半年没有去研究C++技术了。<br />工作的需要，这半年来一直写在javascript，一个让人又爱又恨的语言。简单灵活的语法、却又带来无穷的陷阱。换一种思考角度的开发方式，使习惯于传统语言的我开始的时候难以适应。<br />开发的时候经常在想如何把javascript的好处带入到C++。或许boost的<a href="http://www.boost.org/libs/any/index.html">any</a>、<a href="http://www.boost.org/libs/lambda/index.html">lambda</a> 、<a href="http://www.boost.org/libs/function/index.html">function</a> 、<a href="http://www.boost.org/libs/signals/index.html">signals</a>可以为C++开发带入少少的javascript乐趣。<img src ="http://www.cppblog.com/cyt/aggbug/15090.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyt/" target="_blank">cyt</a> 2006-11-12 17:45 <a href="http://www.cppblog.com/cyt/archive/2006/11/12/15090.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>新版本的Qu</title><link>http://www.cppblog.com/cyt/archive/2006/04/14/5594.html</link><dc:creator>cyt</dc:creator><author>cyt</author><pubDate>Fri, 14 Apr 2006 15:09:00 GMT</pubDate><guid>http://www.cppblog.com/cyt/archive/2006/04/14/5594.html</guid><wfw:comment>http://www.cppblog.com/cyt/comments/5594.html</wfw:comment><comments>http://www.cppblog.com/cyt/archive/2006/04/14/5594.html#Feedback</comments><slash:comments>19</slash:comments><wfw:commentRss>http://www.cppblog.com/cyt/comments/commentRss/5594.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyt/services/trackbacks/5594.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Qu语言又出了新版本，引入了很多新的、吸引人的特性。&nbsp;&nbsp;<a href='http://www.cppblog.com/cyt/archive/2006/04/14/5594.html'>阅读全文</a><img src ="http://www.cppblog.com/cyt/aggbug/5594.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyt/" target="_blank">cyt</a> 2006-04-14 23:09 <a href="http://www.cppblog.com/cyt/archive/2006/04/14/5594.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OCI访问Oracle的一些刁钻问题</title><link>http://www.cppblog.com/cyt/archive/2006/04/14/5591.html</link><dc:creator>cyt</dc:creator><author>cyt</author><pubDate>Fri, 14 Apr 2006 14:24:00 GMT</pubDate><guid>http://www.cppblog.com/cyt/archive/2006/04/14/5591.html</guid><wfw:comment>http://www.cppblog.com/cyt/comments/5591.html</wfw:comment><comments>http://www.cppblog.com/cyt/archive/2006/04/14/5591.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/cyt/comments/commentRss/5591.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyt/services/trackbacks/5591.html</trackback:ping><description><![CDATA[
		<p>1、CLOG/BLOG的插入<br /> 找了很多OCI的例子以及一些PHP的例子，基本上都是同一种做法：<br /> a、OCIStmtPrepare预处理SQL语句："insert into mytable (myimg) values (empty_blob()) returning myimg into :pImg"<br /> b、调用OCIDescriptorAlloc，用参数OCI_DTYPE_LOB，获得一个LOB的句柄<br /> c、用OCIStmtBindByPos或者OCIStmtBindByName，把LOB句柄和参数:pImg绑定<br /> d、OCIStmtExecute执行<br /> e、OCILobWrite往LOB里面写数据<br /> f、commit和释放资源等等<br /> <br /> 问题是这个SQL语句也太特别了，和其他数据库的SQL不一样。但是在java的实现中，并不需要这么奇怪的语法。<br /> insert into mytable (myimg) values(?)<br /> 就足够了。<br /> 在我们的应用中，能够统一同一种SQL的写法当然是最好的，最好就是：<br /> insert into mytable (myimg) values (:pImg) 那就和其他的数据处理一致了。<br /> <br /> 做了很多的尝试，终于找到解决的方法：<br /> a、OCIStmtPrepare预处理SQL语句："insert into mytable (myimg) values (:pImg)"<br /> b、调用OCIDescriptorAlloc，用参数OCI_DTYPE_LOB，获得一个LOB的句柄<br /> c、通过OCILobCreateTemporary函数，为LOB句柄创建临时LOB对象<br /> d、OCILobWriteAppend往LOB句柄写数据<br /> e、用OCIStmtBindByPos或者OCIStmtBindByName，把LOB句柄和参数:pImg绑定<br /> f、OCIStmtExecute执行<br /> g、commit和释放资源等等<br /> <br /> 经过简单的封装，LOB操作简单很多了：<br /> TDBConnection conn = TDatabase::getConnection( strConnection );<br /> TDBStatement dbStatement(conn.getStatement());<br /> dbStatement.prepareSQL( "insert into mytable (myimg) values (:pImg)" );<br /> dbStatement.getParam("pImg").attachInputStream( fStream );<br /> dbStatement.execSQL();<br /> conn.commite();<br /> <br />2、空字符串<br /> 插入一个空字符串，OCIBindByPos/OCIBindByName的时候，那个字符串的数据类型，不能是SQLT_LVC，用SQLT_CHR倒是没有问题。<br /> 具体为什么，只有Oracle自己知道了。<br /> <br />3、指定IP连接Oracle<br /> 通过OCIServerAttach里面指定绑定的SID连接数据库。用SID连接Oracle当然有它的好处。奇怪的是JDBC能用IP和Port指定连接哪个Oracle。<br /> 找遍OCI的帮助都找不到IP连接方法。google了很久，找到解决的方法，自己生成SID：<br /> string strSID = "(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=%1)(PORT=%2)))(CONNECT_DATA=(SERVICE_NAME=%3)))";<br /> 里面的%1设为Oracle服务器的IP；%2设为Oracle服务器的Port，一般是1521；%3就是database的名字。<br /> 把这个字符串放入OCIServerAttach</p>
		<p> </p>
<img src ="http://www.cppblog.com/cyt/aggbug/5591.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyt/" target="_blank">cyt</a> 2006-04-14 22:24 <a href="http://www.cppblog.com/cyt/archive/2006/04/14/5591.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux的系统性能监测参数获取</title><link>http://www.cppblog.com/cyt/archive/2006/03/02/3660.html</link><dc:creator>cyt</dc:creator><author>cyt</author><pubDate>Thu, 02 Mar 2006 14:54:00 GMT</pubDate><guid>http://www.cppblog.com/cyt/archive/2006/03/02/3660.html</guid><wfw:comment>http://www.cppblog.com/cyt/comments/3660.html</wfw:comment><comments>http://www.cppblog.com/cyt/archive/2006/03/02/3660.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/cyt/comments/commentRss/3660.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cyt/services/trackbacks/3660.html</trackback:ping><description><![CDATA[<P>目前的工程需要简单的监测一下Linux系统的：CPU负载、内存消耗情况、几个指定目录的磁盘空间、磁盘I/O、swap的情况还有就是网络流量。<BR>Linux下的性能检测工具其实都有很多。mrtg（<A href="http://people.ee.ethz.ch/~oetiker/webtools/mrtg/">http://people.ee.ethz.ch/~oetiker/webtools/mrtg/</A>）就是一个很不错的选择。不过用mrtg就要装sysstat、apache、snmp、perl之类的东西。而且安装也要好几个步骤，似乎比较麻烦。本来也想直接调用sar、vmstat之类的命令，parse一下结果就算了。哪知道发现不同的版本的linux这些命令的结果也都是不一样。既然要按版本parse它们的结果，那还不如直接去系统里面获得算了。于是研究了一下sysstat（<A href="http://freshmeat.net/projects/sysstat/">http://freshmeat.net/projects/sysstat/</A>）和gkrellm（<A href="http://gkrellm.net">http://gkrellm.net</A> ）的源代码，找到监测性能的数据所在。<BR><BR>1、CPU<BR>&nbsp;&nbsp;&nbsp;在文件"/proc/stat"里面就包含了CPU的信息。每一个CPU的每一tick用在什么地方都在这个文件里面记着。后面的数字含义分别是：user、nice、sys、idle、iowait。有些版本的kernel没有iowait这一项。这些数值表示从开机到现在，CPU的每tick用在了哪里。例如：<BR>cpu0 256279030 0 11832528 1637168262<BR>就是cpu0从开机到现在有256279030 tick用在了user消耗，11832528用在了sys消耗。所以如果想计算单位时间（例如1s）里面CPU的负载，那只需要计算1秒前后数值的差除以每一秒的tick数量就可以了。gkrellm就是这样实现的：((200 * (v2 - v1) / CPU_TICKS_PER_SECOND) + 1) /2<BR>例如，第一次读取/proc/stat，user的值是256279030；一秒以后再读一次，值是256289030，那么CPU在这一秒的user消耗就是：((200 * (256289030 - 256279030) / CPU_TICKS_PER_SECOND) + 1) /2 = ((10000 * 200 / 1000000) + 1) / 2 = 1%了。<BR><BR>2、内存消耗<BR>&nbsp;&nbsp;&nbsp;文件"/proc/meminfo"里面包含的就是内存的信息，还包括了swap的信息。例如：<BR>$ cat /proc/meminfo<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total:&nbsp;&nbsp;&nbsp; used:&nbsp;&nbsp;&nbsp; free:&nbsp; shared: buffers:&nbsp; cached:<BR>Mem:&nbsp; 1057009664 851668992 205340672&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 67616768 367820800<BR>Swap: 2146787328 164429824 1982357504<BR>MemTotal:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1032236 kB<BR>MemFree:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 200528 kB<BR>MemShared:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 kB<BR>……<BR>不过从gkrellm的源代码看，有些版本没有前面那两行统计的信息，只能够根据下面的Key: Value这种各式的数据收集。<BR><BR>3、磁盘空间<BR>&nbsp;&nbsp;&nbsp;从gkrellm的源代码看，这个是一个很复杂的数据。磁盘分区的数据有可能分布在：/proc/mounts、/proc/diskstats、/proc/partitions等等。而且如果想要检查某几个特定的路径，还需要通过mount、df等命令的帮助。为了减少麻烦，这个数据我就直接用statfs函数直接获得了。<BR>int statfs(const char *path, struct statfs *buf);<BR>这个函数只需要输入需要检查的路径名称，就可以返回这个路径所在的分区的空间使用情况：<BR>总空间：buf.f_bsize * buf.f_blocks<BR>空余空间：buf.f_bsize * buf.f_bavail<BR><BR>4、磁盘I/O<BR>&nbsp;&nbsp;&nbsp;磁盘I/O的数据也同样比较复杂，有些版本看/proc/diskstats，有些版本看/proc/partitions，还有些版本至今我也不知道在那里看……不过可以看到数据的版本也像CPU那样，需要隔一段时间取值，两次取值的差就是流量。<BR><BR>5、网络流量<BR>&nbsp;&nbsp;&nbsp;网络流量也是五花八门，不过基本上都可以在/proc/net/dev里面获得。同样也是需要两次取值取其差作为流量值。<BR><BR>&nbsp;&nbsp;&nbsp;以上就是数据获得源头。程序也比较好写，不外乎就是打开一些文件，逐行读出来然后用sscanf来parse一下数据就可以了。</P><img src ="http://www.cppblog.com/cyt/aggbug/3660.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cyt/" target="_blank">cyt</a> 2006-03-02 22:54 <a href="http://www.cppblog.com/cyt/archive/2006/03/02/3660.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>