转:如何让程序屏蔽CTRL+C和CTRL+Z

一个程序在终端运行时,我们可以CTRL+C退出该程序或者CTRL+Z暂时停止该程序。那么有办法屏蔽这两个操作吗?

首先,得明白CTRL+C和CTRL+Z做了些什么。stty是Linux下的命令,输出和设置命令行控制参数。stty -a能输出所有命令行设置。如下是本博的命令行设置:
$stty -a
speed 38400 baud; rows 48; columns 159; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = M-^?; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc ixany imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
可以看到CTRL+C就等于INTR,CTRL+Z就是SUSP,也就是说这两个分别会向程序发送SIGINT和SIGSTOP信号,这两个信号,一个用于终止进程,一个用于暂停进程,即挂起。

信号是Linux系统用于进程间通信的,内核也可以通过它们向程序发送消息。这些信号都很小,Sponge Liu写了篇文章《Linux内核信号处理机制介绍》,深入浅出的走了介绍。

接下来的问题就是,如何屏蔽两个信号。当然,你也可以通过设置stty的方式实现。可以在程序中屏蔽吗?如果可以,如何屏蔽?如果不可以,为啥?

很明显,肯定有些信号不能被屏蔽,比如中断,还应该有杀死进程的信号,要不然内核怎么做操作系统中的老大。实际上,SIGKILL和SIGSTOP信号是不能被屏蔽或阻止的,他们的默认动作总是会被执行的。

那就来个程序,直接屏蔽SIGINT信号吧.
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdbool.h>

bool keep_going = true;

void ignore_notice()
{
  keep_going=false;
  printf("recieved SIGINT,and ignore it.\n");
}

void do_something()
{
  int i=0;
  while(i < 1000000)
    {
      i++;
    }
}

int main ()
{
  if(signal(SIGINT, ignore_notice) == SIG_ERR)
  {
    printf("Fail\n");
    return 1;
  }

  while(keep_going)
    do_something();

  printf("program normally exit.\n");
  return 0;
}

下面语句设置针对SIGINT的动作,第二个参数可以传入函数指针,指定处理方式为函数内容,也可以为SIG_IGN,忽略这个信号,或者SIG_DFL,执行默认的动作。
signal(SIGINT, ignore_notice) == SIG_ERR

转自:http://www.lingcc.com/2010/10/12/11305/

LUA学习(1)lua介绍和与C++混编

    今天闲来没事,学习了下lua,发现lua是一门很好上手的语言,核心很紧凑,而扩展库很多,可以支持socket,多线程,图形编程等。可惜国内的lua社区并不火,但好在有不少前辈已经为我们摸索出了一条康庄大道,并且博客资源很丰富,质量也不错。

Lua是一个嵌入式的脚本语言,它不仅可以单独使用还能与其它语言混合调用。
Lua与其它脚本语言相比,其突出优势在于:

  1. 可扩展性。Lua的扩展性非常卓越,以至于很多人把Lua用作搭建领域语言的工具(注:比如游戏脚本)。Lua被设计为易于扩展的,可以通过Lua代码或者 C代码扩展,Lua的很多功能都是通过外部库来扩展的。Lua很容易与C/C++、java、fortran、Smalltalk、Ada,以及其他语言接口。
  2. 简单。Lua本身简单,小巧;内容少但功能强大,这使得Lua易于学习,很容易实现一些小的应用。并且lua现在的库已经很齐备了,虽然说和python还有差距,但是毕竟二者所专注的领域不同。
  3. 高效率。Lua有很高的执行效率,统计表明Lua是目前平均效率很高的脚本语言,执行效率可以达到C语言的1/10。
  4. 与平台无关。Lua不是通过使用条件编译实现平台无关,而是完全使用ANSI (ISO) C,这意味着只要你有ANSI C编译器你就可以编译并使用Lua。
可以到 http://code.google.com/p/luaforwindows/ 下载lua5.1 for windows版的二进制文件,最新版本是2011年6月放出来的lua 5.1.45,这也是我使用的版本。其已经内置了很多常用的库,以及一个继承的开发环境scite,以及一堆example和手册,以及一个QuickLuaTour。安装过程不详述了。
安装后,打开scite,输入代码后按F5,即可完成编辑和执行的过程。
注意:lua虽然属于脚本,但是仍有一个编译的过程,会编译成luac为后缀的字节码文件,也可直接解释执行。

第一个例子
print("hello world")
print "hello world"

运行后即可看到结果。需要注意的是lua代码没有分号作为结尾的,也没有控制结构中常见的花括号{}。
完整的demo如下:
print("Hello World.".."haha")
-- 两个下划线是注释
-- print 5*2 这样是错误的,只有字符串和table才能不加引号
print(5*2)
-- 自定义函数,没有{},也没有分号
function gougudli(a,b)
    local c2=a^2+b^2
    return math.sqrt(c2)
end
print(gougudli(6,8))
--循环和判断结构
for i=1,15,2 do
-- lua中用两个点连接变量
print("now i is\t"..i)
if i<2 then
print("small")
elseif i<7 then
print "medium"
else
print("big")
end
end
index=1
repeat
index=index+1
print(index)
until index==6
--table是LUA里重要并且唯一的复合数据结构
mydata={}
mydata[0]=1985
mydata["name"]="waitfox"
for key,value in pairs(mydata) do
print(key.."="..value)
end
-- 可变参数的函数
function free_print(...)
for i=1,arg.n do print(arg[i]) end
end
free_print("one","two")
--以table作参数
function print_table(t)
for k,v in pairs(t) do print(v) end
end
print_table{1,2,5,"good",10}

前面还说过,lua是很容易扩展的,并且与C有很亲的血缘关系,那么lua与C混编也应该是很容易实现的了。
示例如下:
(1)使用MSVC新建一个空的工程,这里我用的是VC6。在工具-选项-目录中设置好头文件和lib库的地址;
(2)工程-属性,在对象/库模块中添加 lua51.lib;
(3)代码如下:
#include "stdafx.h"
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
int main(int argc, char *argv[]) {   
lua_State *L = lua_open();//装载lua堆栈
luaL_openlibs(L);
   if (NULL == L)
   {
      printf("Error Initializing lua\n");
      return -1;
   }
char line[BUFSIZ];
while (fgets(line, sizeof(line), stdin) != 0){    
luaL_dostring(L,line);
 }
 lua_close(L);
return 0;
}

编译-组建后,即可看到你需要的结果,将出现一个窗口,输入单行LUA命令,即可执行lua脚本。
如图所示:
2011-09-14_163219.jpg
注意:(1)lua5.1不论是和lua4或者是lua5.0相比,其一些宏定义和函数用法都有了一些变化。如果你是在网上看到的教程,无法运行,或运行结果与期望不符,很可能是版本问题。
(2)如果在编译过程中出现以下错误,请严格按照示例代码引入头文件,并使用正确的函数名。
比如:
cannot convert from 'int' to 'struct lua_State *' 这是由于没有引入lauxlib.h造成的。
'lua_dostring' : undeclared identifier 这是由于lua5.1中此函数名不存在造成的,实际上此函数已经更名为luaL_dostring。
可能网上很多示例都是基于较早的版本,尤其需要注意,你遇到的种种疑难杂症,很可能就是版本问题。
BTW:scite存在选择半个中文字乱码,或者是编辑中文时就会乱码。这需要修改global 配置文件。
修改下面的选项为:
code.page=936
output.code.page=936

C语言中的序列点

此文针对phpchina中的一篇文章而写,可到此围观。
http://bbs.phpchina.com/thread-221621-1-3.html
#include<stdio.h>
main(){
       int i=5,j=5,q,p;
       p = (++i)+(++i)+(++i);
       q = (j++)+(j++)+(j++);
       printf("%d,%d",p,q);
       system("pause");
}
打印出 :22,15
<?php
$i=5;
$m=5;
$b = (++$m)+(++$m)+(++$m);
$d = ($i++)+($i++)+($i++);
echo $b,'--',$d;
输出:21--18
为啥不一样呢?
C的输出感觉不对似的。。。用linux的GCC 和win下面的DEV C++都是 22,15 。。。跟什么有关系吗?

      这个问题其实就是C里面常常被提到的序列点问题,此代码的执行顺序由编译器自行决定。先介绍两个概念。
     副作用:对数据对象或者文件的修改。
    序列点:是一个时间点(在整个表达式全部计算完毕之后或在 ||、 &&、 ? : 或逗号运算符处, 或在函数调用之前), 此刻尘埃落定, 所有的副作用都已确保结束。

阅读剩余部分...

如何查看你可以分配多大内存

#include <stdio.h>
#include <stdlib.h>

int main(void){
    int MB = 0;
    while(malloc(1 << 20))
        ++MB;
    printf("Allocated %d MB total\n", MB);

    return EXIT_SUCCESS;
}

原理,因为2的20次方就是1MB(2的10次方为1KB,2的30次方为1GB,以此类推)。

如果你请求分配的内存块小于1MB,你得到的内存是否比这要多一些呢?为什么?

答:

这不是绝对的!

在本例中使用

1<<22(4MB)得到的结果乘4是2000MB

1<<21(2MB)得到的结果乘2是1972MB

1<<20(1MB)得到的结果是1918MB

1<<19(0.5MB)得到的结果除2是1812MB

1<<18(0.25MB)得到的结果除4是2003MB

1<<17(0.125MB)得到的结果除8是2034MB

显然出现了一个意外的结果。

windows上配置Code::Blocks的wxWidgets以及hello world示例

    很早就安装了Code::Blocks,本来一直想搞VC开发的,今天特意比较了下GTK,QT4,wxsmith这几款windows下的跨平台GUI工具。GTK太老,界面也很丑,安装很麻烦,就没考虑。QT4据说不错,也下了,但没有配置好一个比较合适的开发环境,故还没尝试。由于我安装了Code::Blocks,并且Code::Blocks自带了wxsmith的插件,那就先体验下 wxsminth把。
    首先,下载Code::Blocks 10.05最新的安装包,内置包含mingw的那一个,大约74M。如果要自己配置mingw的话也可以,不过真的很麻烦。GNU的东西要在windows下跑起来很恶心的,咱就还是搞人家编译好的吧。
   下载地址:http://www.codeblocks.org/downloads/26.下载后,安装到任意路径。
    然后,下载wxPack。你也可以下载wxWidgets源代码自行编译,但这真是吃力不讨好,即容易出错,又很耗时。这里我们下载wxPack v2.8.11.03。下载页面:http://wxpack.sourceforge.net/Main/Downloads.它是居于最新的wxWidgets2.8.11编译的。这个安装包有259.9M。但是如果你全部安装的话,有2.5G大小。我们直接安装它,在安装时,会出现一个选择界面,选择安装MSVC和GCC/MINGW版本,若只安装MSVC,要700M空间,若安装GCC/MINGW,则需要2G空间。在这里,为了以后的方便,少些麻烦,我们选择全部安装。反正硬盘不值钱,别舍不得你那点硬盘.假设我们能装在e:/dev/wx目录下(安装目录最好不要带空格和中文)。
     到此为止,基本的环境安装完毕。现在开始开发。
(1)打开code::blocks,选择新建wxWidgets project。

1.png

阅读剩余部分...

转:PHP程序员的C语言学习之路-C语言指针初体现

要了解C语言的指针,首先应该了解内存的结构。下面我先介绍一下内存的结构吧,let’s go

内存就像一个个编好号码的盒子,如下图:
c1.jpg

我们可以任意选择其中的一个盒子存放东西,例如我们要在第一个盒子中放入10个乒乓球,所以我们可以找到编号为1的盒子,然后把10个乒乓球放进里面。

 

计算机的内存跟上面的例子很相似,因为内存也有编号,也可以往里面放东西,所以本质上跟上面的例子没有什么区别的。我们看看内存的真实结构吧:

c2.jpg

在上面的图中,我们看到的图片左边的一些16进制数值就是内存的编号,我们称他为内存地址。而白色框框里面的数据就是保存在内存中的实际数据,我们一般使用的就是这些数据。

好了,已经大概了解过计算机的内存结构了,下面我们来说说什么是指针吧。

定义:指针是一种数据类型,与其它的数据类型不同的是指针是一种用来存放内存的地址的变量。

从上面的定义上可以看出,指针是变量,而且是有类型的变量,但他保存的是内存的地址。这样说来,指针也是很容易理解的。的确,指针就是这么容易。不过要灵活运用指针才能发挥出C语言的最大优势。

 

阅读剩余部分...

PHP程序员的C语言学习之路系列之第二章-C语言里的函数(1)

    C语言的风格是过程式的,按照正常的人类思维,用函数的方式来表达一个处理过程是我们非常习惯的思维方式,因此C语言的运行单位是函数。 (面向对象的思维方式不是正常人的思维习惯,是抽象到一定程度的思维,所以面向对象才那么的难以理解)每一个C语言代码都是以如下基本结构为蓝图的:
//起床函数
void getup()
{
}
//吃饭函数
void eat()
{
}
//睡觉函数
void sleep()
{
}
int main(void)
{
    // 每天重复的生活
    getup();
    eat();
    sleep();
    return 0;
    // 这之后就是我们无法控制的梦乡。。。有可能有一天永远也醒不来了。
   //return后一切over
}
    编写程序也就是按照一定的次序执行不同的功能,最后完成我们的各种目的。这就是C语言里以函数为单元组织编程的思路。那我们先来看看函数的定义和使用。
在C语言里,和php不同的是,变量都需要先声明后使用,函数也是如此。所以你需要先声明一个函数类型,然后才能使用。
先运行下面的代码看看:
#include <stdio.h>
#include <stdlib.h>
int sum;
int add(int x,int y);//声明函数原型
int main()
{
    int arr[]={ 10,20,30 };
    printf("the middle is %d\n",arr<:1:>);
    sum=add(3,5);
     printf("%d",add(7,8));
    return 0;
}
int add(int x,int y)
{
    printf("函数名是:%s\n",__func__);//类似地C也有PHP里类似的魔术常量
    return x+y;
}
   如果add函数在main函数之前定义,那么就不需要声明了。这点和php是不一样的,php的函数可以放在调用之前或之后(当然,也有特例),也不需要实现声明,更不需要返回类型。这点很好理解。
main函数是程序里第一个要执行的函数,其他的函数都可以认为是这个函数的子函数。
函数定义的原型:
类型 名称(参数声明){
函数体
}
类型可以是基本类型,如int变量,也可以是指针,void,还可以包含其他修饰符。
和php一样,C里的函数也可以在另一个文件里声明,然后引入这个文件。如下:
先新建一个test.c文件
#include <stdio.h>
#include "test.h"

int test(char *str)
{
    printf("%s\n", str);
    return 0;
}
通常,为了方便说明一个代码中包含了哪些可以被调用的函数,或者可以被操作的数据,我们需要编写一个头文件作为介面定义,让其他代码可以访问该文件中的函数或者变量,通常取与被描述的代码相同的名字.因此,我们再定义一个test.h文件
#ifndef __TEST_H__          // 如果未定义该宏,则定义出来,防止多次被include
#define __TEST_H__

// 这里开始写对test.c的内容的描述
extern int test(char *str); // 注意结尾必须有分号,extern后重新输入一遍定义

#endif
然后是主文件
#include "test.h"                 // 包含我们对test.c的定义

int main(void)
{
    test("Hello World !");  // 调用我们自己的test函数实现打印
    return 0;
}
是不是和php里的include很像呢,这样就能更好的组织你的代码了.

转:PHP程序员的C语言学习之路系列之第一章, C语言的一些基础

(1)  基本数据类型
     在学习PHP的时候你可能不用知道什么是数据类型, 就算PHP有很多数据类型如: “字符串类型”, “整数类型”, “浮点型类型”等, 但是PHP的数据类型跟C语言的数据类型还是有很大差别的. 为什么这样说? 因为PHP把C语言的数据类型抽象化了. 下面我们想来学习一下C语言的数据类型吧.
    PHP是弱类型语言, 而C语言是强类型语言, 也就是说如果你想使用C语言的变量, 那么你首先要知道变量的类型. 而不像PHP那样变量可以是任何的类型. 另外如果你想使用C语言的变量, 那么你必须先声明这个变量, 然后才可以使用. 如下:

int ivar;
ivar = 10;
如果你没有声明而直接使用变量, 编译会不通过, 如下是错误的:

ivar = 10;
因为PHP不用声明变量就能使用, 所以PHP程序员写C程序时要特别注意声明变量. C语言声明的方式是:
类型 变量名;

如:
int ivar; //定义一个名为ivar的整型变量
char cvar;//定义一个名为cvar的字符型变量
float fvar;//定义一个名为fvar的浮点型变量
double dvar1, dvar2, dvar3;//定义3个双精度类型的变量
long lvar1, lvar2, lvar3;//定义3个长整型的变量

阅读剩余部分...

    Page :
  1. 1
  2. 2