《Linux程序设计》读书笔记(一)

 

《Linux程序设计》读书笔记


1、编译C程序的技巧

    在调用C语言编译器的时候可以通过给出“-I”标志来引用保存在下级子目录或者非标准目录下的头文件,如:
        $ gcc -I /usr/openwin/include fred.c
它会使编译器在/usr/openwin/include的子目录和标准目录两个地方去查找fred.c程序里所包含的头文件。

    用grep查找含有某些特定定义与函数生命的头文件是很方便的。如:
        $ grep EXIT_ *.h
grep命令会在该子目录下的所有名字以.h结尾的文件里查找字符串“EXIT_”。

2、库文件
   
标准的系统库文件一般保存在/lib或/usr/lib子目录中。库文件的名字永远以“lib”这几个字母打头,随后便是函数库说明的部分(比如用c表示
这是一个C语言函数库,用m表示一个数学运算库),文件名的最后部分以一个“.”开始,然后给出这个库文件的类型:静态函数库.a;共享函数库.so
或.sa。
    在通知编译器查找某个库文件的时候,既可以给出其完整的路径名,也可以使用“-l”标志,。如:
        $ cc -o fred fred.c /usr/lib/libm.a

        $ cc -o fred fred.c -lm
-lm代表标准目录库中名为libm.a的函数库。 更详细的解释参见下面的例子。
    虽然库文件与头文件相似,都是被保存在某个标准位置,但我们仍然可以通过“-L”标志给编译器增加搜索子目录库。如:
        $ cc -o x11fred -L/usr/openwin/lib x11fred.c -lX11
该命令在编译和链接程序x11fred时将使用在子目录/usr/openwin/lib中找到的libX11函数库版本。

    2.1 静态库(archive)
    假设现有源文件bill.c和fred.c,则建立静态库的方法:
    (1)编译源文件生成二进制目标文件,需要在调用C编译器时加上“-c”选项以防止生成最终应用程序。
        $ cc -c bill.c fred.c
    (2)为函数库建立一个头文件(lib.h),它的作用是在我们的函数库里对这两个函数进行声明;如果有程序要使用这个函数库,就必须使用include引用。
    (3)调用程序(program.c)引用库函数头文件并调用其中的函数。
    (4)使用ar工具简历档案并把目标代码加入其中。
        $ ar crv libfoo.a bill.o fred.o
  
    另外,某些系统(尤其是Berkley UNIX操作系统发展而来的系统)上,要想成功是用函数库,必须先为这个函数库建立一个内容表:
        $ ranlib libfoo.a

    可以通过使用“-L”选项告诉编译器静态库的位置:
        $ cc -o program program.o -L. -lfoo
“-L.”告诉编译器在当前子目录中查找函数库。“-lfoo”选项告诉编译器使用那个名为libfoo.a的函数库(或者一个名为libfoo.so的共享库,如果有的话)。

    可以使用nm命令查看某个目标代码文件、函数库或者可执行程序里都包含那些函数。

    2.2 共享库
   
如果一个程序使用了共享库,它的连接方式是这样的:它本身不再保存函数的代码,而只保存共享代码的调用线索,共享代码是在运行的时候才加入其中的。对
Linux系统而言,负责加载共享库并解析客户程序中函数调用线索的程序(即共享库动态加载器)是ld.so或ld-linux.so.2;查找共享库的
其他地点是在/etc/ld.so.conf文件里配置的;如果这个文件进行了修改,就需要用ldconfig命令进行处理。
    可以使用ldd程序查看某个程序要求使用的是哪一个共享库:
        $ ldd program

    .so类似于Windows中的.DLL文件,是运行时加入程序的;.sa类似于Windows中的.LIB文件,是加入到可执行文件里面的。

3 基本的Shell命令
3.1 Redirecting Output
    管道重定向:>
    对文件追加:>>
    For
">", by default, if the file already exists, then it will be
overwritten. If you want to change the default behavior, you can use
the command set -o noclobber (or set -C), which sets the noclobber option to prevent a file from being overwritten using redirection. You can cancel this option using set +o noclobber.
    For ">>", outputs are appended to the end of the file.

   
File descriptor 0 is the standard input to a program, file descriptor 1
is the standard output, and file descriptor 2 is the standard error
output. It’s unusual to want to redirect any other than the standard
ones: 0, 1, and 2.

    To redirect the
standard error output, preface the > operator with the number of the
file descriptor you wish to redirect. Because the standard error is on
file descriptor 2, use the 2> operator. This is often useful to
discard error information and prevent it from appearing on the screen.

    The command
     $ kill -HUP 1234 >killout.txt 2>killerr.txt
will put the output and error information into separate files.

    If you prefer to capture both sets of output into a single file, you can use the >& operator to combine the two outputs. Therefore,
     $ kill -1 1234 >killouterr.txt 2>&1
will
put both the output and error outputs into the same file. Notice the
order of the operators. This reads as “redirect standard output to the
file killouterr.txt, and then direct standard error to the same place
as the standard output.” If you get the order wrong, the redirect won’t
work as you expect.

3.2 Redirecting Input
    <

3.3 Pipes
    Processes connected by pipes can run simultaneously and are automatically rescheduled as data flows between them.

3.4 file command
    The best way to check if a file is a script or not is to use the file command — for example, file first or file /bin/bash.

4 Shell Scripts

P60, to be continued...

类成员函数指针浅析

今天看某软件的源代码时,发现有这样一行

  1. typedef CPB_RETVAL (CPBprb_Prb::*CPBprb_action)(CPBprb_Prb &, unsigned);

其中CPB_RETVAL是一个enum类型,CPBprb_Prb是一个类,CPBprb_action在代码中其他地方没有找到定义。因不知这行代码所为何意,遂在论坛发贴请教http://topic.csdn.net/u/20080908/11/0f127830-8c90-414d-9bab-5d946b115522.html?seed=1500702230

承蒙众多高手赐教,才知上段代码定义了成员函数指针类型CPBprb_action,该类型函数有2个参数,类型分别为CPBprb_Prb &, unsigned,返回值类型为CPB_RETVAL。此函数指针的类型有个定义域,它是类CPBprb_Prb的成员(CPBprb_Prb::*CPBprb_action)。

另外,CPBprb_action不仅可以指向CPBprb_Prb的成员函数,也可以指向CPBprb_Prb的派生类成员函数。甚至,CPBprb_Prb里可以根本就没有任何诸如CPB_RETVAL functionName (CPBprb_Prb &, unsigned)这样的函数,而完全可以在CPBprb_Prb的派生类里去增加 CPB_RETVAL functionName (CPBprb_Prb &, unsigned);这样的函数,如:

  1. #include <iostream>
  2. class A
  3. {
  4. public:
  5.     A(){};
  6.     virtual ~A(){};
  7. };
  8. class B : public  A
  9. {
  10. public:
  11.     B(){};
  12.     ~B(){};
  13.     int Fb(int a){ return a*a;}
  14. };
  15. typedef int (A::*Myfunction)(int);
  16. int main()
  17. {
  18.     B* pB = new B;
  19.     Myfunction pf = (Myfunction)(&B::Fb);
  20.     int retValue = (pB->*pf)(3);
  21.     std::cout<<retValue;
  22.     std::cin>>retValue;
  23.     return 1;
  24. }

通过typedef int (A::*Myfunction)(int);定义的Myfunction是A的成员(函数指针),但只能在类外定义。

需要指出的是,使用指向成员函数的指针变量是比较危险的!因此不建议这么用。

上文引用了论坛中对我帖子的回复,再次对关心并帮助我的人表示感谢。

PS:

函数指针(全局函数/类成员函数)和函数对象

(原文链接:http://www.ccrun.com/article.asp?i=1005&d=sc37og

关键字:函数指针 全局函数 类成员函数 函数对象 Function object

作者:ErranLi    更新:2007-01-06 02:31:47    浏览:9166

函数指针(全局函数/类成员函数)、函数对象(Function object)

一. 函数指针类型为全局函数.

#include "stdafx.h"

#include <iostream>
using namespace std;

class TestAction;

typedef void (*fp)(int);

void Drink(int i)
{
    cout<<"No. "<<i<<" drink..."<<endl;
}

void Eat(int i)
{
    cout<<"No. "<<i<<" eat..."<<endl;
}

class TestAction
{
public:
    fp testAct;

    void TestAct(int i)
    {
        if (testAct != NULL)
        {
            testAct(i);
        }
    }
};

int main(int argc, char* argv[])
{
    TestAction doact;
    doact.testAct = &Drink;
    doact.TestAct(0);
    doact.TestAct(1);
    doact.TestAct(2);
    doact.testAct = &Eat;
    doact.TestAct(0);
    doact.TestAct(1);
    doact.TestAct(2);
    return 0;
}

二. 函数指针类型为类成员函数.

#include "stdafx.h"

#include <iostream>
using namespace std;

class Action;
class TestAction;

// 函数指针类型为类 Action 的成员函数
typedef void (Action::*fp)(int);

class Action
{
public:
    void Drink(int i)
    {
        cout<<"No. "<<i<<" drink..."<<endl;
    }

    void Eat(int i)
    {
        cout<<"No. "<<i<<" eat..."<<endl;
    }
};

class TestAction
{
public:
    // 定义一个函数指针
    fp testAct;
    //Action 对象实例 , 该指针用于记录被实例化的 Action 对象
    Action * pAction;

    void TestAct(int i)
    {
        if ((pAction != NULL) && (testAct != NULL))
        {
            // 调用
            (pAction->*testAct)(i);
        }
    }
};

int main(int argc, char* argv[])
{
    Action act;
    TestAction doact;
    doact.pAction = &act;
    doact.testAct = &Action::Drink;
    doact.TestAct(0);
    doact.TestAct(1);
    doact.TestAct(2);
    doact.testAct = &Action::Eat;
    doact.TestAct(0);
    doact.TestAct(1);
    doact.TestAct(2);
    return 0;
}

三. 函数对象 (Function object)
// 本文转自 C++Builder研究 - http://www.ccrun.com/article.asp?i=1005&d=sc37og

#include "stdafx.h"

#include <iostream>
#include <functional>

using namespace std;

class Action;
class Drink;
class Eat;
class TestAction;

class Action
{
public:
    int operator()(int i)
    {
        Act(i);
        return i;
    }

    virtual void Act(int i) = 0;
};

class Drink : public Action
{
    void Act(int i)
    {
        cout<<"No. "<<i<<" drink..."<<endl;
    }
};

class Eat : public Action
{
    void Act(int i)
    {
        cout<<"No. "<<i<<" eat..."<<endl;
    }
};

class TestAction
{
public:
    void TestAct(int i, Action& testAct)
    {
        testAct(i);
    }
};

int main(int argc, char* argv[])
{
    TestAction doact;
    doact.TestAct(0, Drink());
    doact.TestAct(1, Drink());
    doact.TestAct(2, Drink());
    doact.TestAct(0, Eat());
    doact.TestAct(1, Eat());
    doact.TestAct(2, Eat());
    return 0;
}

虽然传递函数指针被广泛应用于事件驱动系统中,以此实现回调函数通过指针来调用。但 C++ 还是提供了另外一种可供选择的办法,即函数对象,利用它可以
避免使用函数指针。这样做有几个优点。首先, 因为对象可以在内部修改而不用改动外部接口,因此设计更灵活,更富有弹性。函数对象也具备有存储先前调用结
果的数据成员。。 此外,编译器可以内联函数对象,从而进一步增强性能。函数对象可以具体表达依赖成员模板的通用算法 , 这些算法借助普通的函数指针难
以完成。例用函数对象实现了一个通用的 Negation 算法操作:

#include "stdafx.h"
#include <iostream>

using namespace std;

class Negate
{
public:
    template<class T> T operator()(T t) const
    {
        return -t;
    }
};

void Callback(int n, const Negate& neg)  // 传递一个函数对象
{
    n = neg(n);  // 调用重载的 () 操作 来对 n 进行 negate 操作
    cout << n << endl;
}

int main(int argc, char* argv[])
{
    // 调用方式一
    Callback(5, Negate());

    // 调用方式二
    Negate neg;
    cout << neg(9.99999) << endl;
    cout << neg(__int32(39999999)) << endl;

    return 0;
}

    STL 库中定义了很多函数对象以供相关算法调用,如 模板化的函数对象 greater<> 或者 less<>:

vector <int> vi;
//.. 填充向量
sort(vi.begin(), vi.end(), greater<int>() );// 降序 (descending)
sort(vi.begin(), vi.end(), less<int>() ); // 升序 (ascending)

本文转自:http://www.cppblog.com/erran/archive/2006/12/26/16868.html

函数对象(function 
object),又名仿函数(functor),是重载了operator()的一个类,其实在stl算法中有大量运用,c++标准预定义的如
less <>,greater <>,bind2nd <>等 
  为什么引入仿函数? 
  原因: 
  1.仿函数有具体型别,可用在模板参数,而函数不行 
  2.同类仿函数可有不同植,可代表不同状态,比函数灵活(须定义多个) 
  3.仿函数可能比普通函数快 
  ........可能还有,不过凭印象就这些了

函数对象

看到有个概念叫“函数对象”,搜了一下关于它的解释:


数对象(function 
object),又名仿函数(functor),是重载了operator()的一个类,其实在stl算法中有大量运用,c++标准预定义的如
less <>,greater <>,bind2nd <>等 
  为什么引入仿函数? 
  原因: 
  1.仿函数有具体型别,可用在模板参数,而函数不行 
  2.同类仿函数可有不同植,可代表不同状态,比函数灵活(须定义多个) 
  3.仿函数可能比普通函数快 
  ........可能还有,不过凭印象就这些了

  和普通函数相比,在不破坏接口的情况下,函数对象可以有自己的状态.

另外,

1 什么是函数对象

c++在模板方面使用很多的一个技术,写一个类,这个类有个成员函数,可以让类象函数一样运行。
主要用于模板函数中。

2 实现

类的成员函数,()可以让一个类运行起来象一个函数一样,如我们在排序的时候我们使用sort
可能sort是这样的sort(int, int)
我们自己可以写一个类,其中重载void operator()(int, int)来实现。

for_each(begin, end, func)
这个func如果是函数的话,会把value(*it)放在函数的参数位置上,如果是一个类在那个位置,将会调用运算符函数()来将参数传递进去。首先调用构造函数,构造函数初始化一个对象后,对象调用函数()来实现函数对象操作。

3 函数对象的优势

函数对象的功能于函数的功能是一样的,那为什么要使用默认构造函数。
1 函数对象是一个智能对象,他可以利用对象中的成员函数,和成员变量。
2 完全可以使用类的优势,可以使用类的重载特性,同样的一个类的名字,可以调用各种函数。

more exceptional c++The C++ Programming Language等书里有看到。

函数对象示例:

  1. // Negate.cpp
  2. #include <iostream>
  3. using namespace std;
  4.  
  5. class Negate
  6. {
  7. public:
  8.        template<class T> T operator()(T t) const
  9.        {
  10.               return -t;
  11.        }
  12. };
  13. void Callback(int n, const Negate& neg)  // 传递一个函数对象
  14. {
  15.        n = neg(n);  // 调用重载的 () 操作 来对 n 进行 negate 操作
  16.        cout << n << endl;
  17. }
  18. int main(int argc, char* argv[])
  19. {
  20.        // 调用方式一
  21.        Callback(5, Negate());
  22.        // 调用方式二
  23.        Negate neg;
  24.        cout << neg(9.99999) << endl;      
  25.        cout << neg(__int32(39999999)) << endl;
  26.        getchar();
  27.        return 0;
  28. }

PS:

定义函数对象

时间:2001/02/07 15:22 作者:vckbase VC知识库


  尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数的方法,那就是函数对象。函数对象(也称“算符”)是重载了“()”操作符的普通类对象。因此从语法上讲,函数对象与普通的函数行为类似。

用函数对象代替函数指针有几个优点,首先,因为对象可以在内部修改而不用改动外部接口,因此设计更灵活,更富有弹性。函数对象也具备有存储先前调用
结果的数据成员。在使用普通函数时需要将先前调用的结果存储在全程或者本地静态变量中,但是全程或者本地静态变量有某些我们不愿意看到的缺陷。

其次,在函数对象中编译器能实现内联调用,从而更进一步增强了性能。这在函数指针中几乎是不可能实现的。

下面举例说明如何定义和使用函数对象。首先,声明一个普通的类并重载“()”操作符:

class Negate

{

public:

int operator() (int n) { return -n;}

};

重载操作语句中,记住第一个圆括弧总是空的,因为它代表重载的操作符名;第二个圆括弧是参数列表。一般在重载操作符时,参数数量是固定的,而重载“()”操作符时有所不同,它可以有任意多个参数。

因为在Negate中内建的操作是一元的(只有一个操作数),重载的“()”操作符也只有一个参数。返回类型与参数类型相同-本例中为int。函数返回与参数符号相反的整数。

使用函数对象

我们现在定义一个叫Callback()的函数来测试函数对象。Callback()有两个参数:一个为int一个是对类Negate的引用。Callback()将函数对象neg作为一个普通的函数名:

#include

using std::cout;

void Callback(int n, Negate & neg)

{

int val = neg(n); //调用重载的操作符“()”

cout << val;

}

不要的代码中,注意neg是对象,而不是函数。编译器将语句

int val = neg(n);

转化为

int val = neg.operator()(n);

通常,函数对象不定义构造函数和析构函数。因此,在创建和销毁过程中就不会发生任何问题。前面曾提到过,编译器能内联重载的操作符代码,所以就避免了与函数调用相关的运行时问题。

为了完成上面个例子,我们用主函数main()实现Callback()的参数传递:

int main()

{

Callback(5, Negate() ); //输出 -5

}

本例传递整数5和一个临时Negate对象到Callback(),然后程序输出-5。

模板函数对象

从上面的例子中可以看出,其数据类型被限制在int,而通用性是函数对象的优势之一,如何创建具有通用性的函数对象呢?方法是使用模板,也就是将重载的操作符“()”定义为类成员模板,以便函数对象适用于任何数据类型:如double,_int64或char:

class GenericNegate

{

public:

template T operator() (T t) const {return -t;}

};

int main()

{

GenericNegate negate;

cout<< negate(5.3333); // double

cout<< negate(10000000000i64); // __int64

}

如果用普通的回调函数实现上述的灵活性是相当困难的。

标准库中函数对象

C++标准库定义了几个有用的函数对象,它们可以被放到STL算法中。例如,sort()算法以判断对象(predicate
object)作为其第三个参数。判断对象是一个返回Boolean型结果的模板化的函数对象。可以向sort()传递greater<>或
者less<>来强行实现排序的升序或降序:

#include // for greater<> and less<>

#include //for sort()

#include

using namespace std;

int main()

{

vector vi;

//..填充向量

sort(vi.begin(), vi.end(), greater() );//降序( descending )

sort(vi.begin(), vi.end(), less() ); //升序 ( ascending )

}

C语言函数中定义大数组耗尽堆栈的问题

今晚上一同学请我帮忙看一个C程序,GCC编译时一直抱错,说是段错误。
程序本身写的比较差,但编译能通过,只是有几十个警告。
两个小时过去了,在Eclipse+GCC下没有找到问题(这个环境还不熟悉),换到了VC下面,逐步调试,才发现问题出在被main调用的一个叫做readmctal()的函数的前面几行中。该函数如下:

  1. void readmctal(void)
  2. {
  3.     int number,count,sign,num_tally,nflag;
  4.     int ncell,nstep,mstep,sum;
  5.     char *(str_temp[80]);
  6.     float temp_spectra[num_cell][egroup],temp_error[num_cell][egroup];
  7. float temp_flux[num_cell],temp_flux_error[num_cell];
  8.     int total_cell_no[num_cell];
  9.     sum=0;  
  10.     number=0;
  11.     /* open the mctal file */
  12.     if ((fpt_mc=fopen("mctal","r"))==NULL){
  13.         printf("/nERROR - Cannot open mctal file/n");
  14.         exit(1);
  15.     }
  16.     else
  17.     {
  18.         printf("File mctal opened.../n");
  19.     }
  20.     ......

同时

  1. # define num_cell 9999
  2. # define egroup 175

定义的二位数组实在是太大了。看了反汇编之后感觉貌似是堆栈的问题,试着将
float temp_spectra[num_cell][egroup],temp_error[num_cell][egroup];
float temp_flux[num_cell],temp_flux_error[num_cell];
移动到函数体外,大功告成!
到Linux下用GCC编译,“段错误”的提示消失了。

经过分析,我认为一个函数分配的内存是有限的,在函数体内定义的二维数组太大了,耗尽了堆栈,因此报错。

PS:论坛达人的观点:
养成良好的编程习惯,一般公司都有coding style,里面应该有规定:
函数内部(局部变量)禁止定义大数组,而应使用动态内存;如数组需传入函数应使用指针作为参数;
其实就算你调用这个函数不出错,但是如果函数嵌套很多的话也会发生segment error
在某些资源有限的系统下,更需要注意这个问题,比如51单片机

函数内是在栈分配内存,栈大小一般限制在1M到2M
函数外则是全局变量,在DATA段分配内存

PSPS:转一篇关于C内存分配的文章,原文链接http://www.lupaworld.com/bbs/viewthread.php?tid=29577

浅谈C内存分配

很早之前写的了,现在发到C版来。

关于C语言内存方面的话题要真说起来的话那恐怕就没头了,所以本文仅仅是一个浅谈。
关于内存问题不同平台之间有一定的区别。本文所指的平台是x86的Linux平台
用C语言做程序(其实其他语言也一样),不仅要熟悉语法,其实很多相关的背景知识也很重要。在学习和研究C语言中内存分配的问题前,首先要了解一下Linux分配给进程(运行中的程序)的地址空间是什么样的。
总的来说有3个段,即代码段,数据段和堆栈段(学过汇编的朋友一定很熟悉了)。代码段就是存储程序文本的,所以有时候也叫做文本段,指令指针中的指令就是
从这里取得。这个段一般是可以被共享的,比如你在Linux开了2个Vi来编辑文本,那么一般来说这两个Vi是共享一个代码段的,但是数据段不同(这点有
点类似C++中类的不同对象共享相同成员函数)。数据段是存储数据用的,还可以分成初始化为非零的数据区,BSS,和堆(Heap)三个区域。初始化非零
数据区域一般存放静态非零数据和全局的非零数据。BSS是Block Started by
Symbol的缩写,原本是汇编语言中的术语。该区域主要存放未初始化的全局数据和静态数据。还有就是堆了,这个区域是给动态分配内存是使用的,也就是用
malloc等函数分配的内存就是在这个区域里的。它的地址是向上增长的。最后一个堆栈段(注意,堆栈是Stack,堆是Heap,不是同一个东西),堆
栈可太重要了,这里存放着局部变量和函数参数等数据。例如递归算法就是靠栈实现的。栈的地址是向下增长的。具体如下:
========高地址     =======
程序栈             堆栈段
         向下增长
“空洞”           =======
         向上增长

------             数据段
BSS
------
非零数据
=========低地址    =======
=========          =======
代码               代码段
=========          =======
需要注意的是,代码段和数据段之间有明确的分隔,但是数据段和堆栈段之间没有,而且栈是向下增长,堆是向上增长的,因此理论上来说堆和栈会“增长到一起”,但是操作系统会防止这样的错误发生,所以不用过分担心。
有了以上理论做铺垫,下面就说动态内存的分配。上面说了,动态内存空间是在堆中分配的。实现动态分配的也就是下面几个函数:
stdlib.h :
void *malloc(size_t size);
void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);
void free(void *ptr);
一个一个说吧。malloc就是分配一个size大小的内存空间,并且用一个void类型的指针指向这个空间,然后返回这个指针。也就是说,malloc
返回了一个指向size大小的空间的void类型的指针,如果要使用这个空间,还得把void*类型转换成一个你需要的类型,比如int*之类。
calloc和malloc基本一样,不同的是有两点,一是calloc分配的空间大小是由nmemb*size决定的,也就是说nmemb是条目个数,
而size可以看成是条目的大小,计算总空间任务由calloc去做。二是calloc返回的空间都用0填充,而malloc则不确定内存中会有什么东
西。realloc是用来改变已经分配的空间的大小。指针ptr是void类型的,它应该指向一个需要重新分配大小的空间,而size参数则是重新分配之
后的整个空间大小,而不是增加的大小。同样,返回的是一个指向新空间的指针。free用来释放由上面3个函数分配的空间,其参数就是指向某空间的指针。
基本就这些了,这些都是比较基础的话题,高级话题和细节问题还有很多,这里就不进行说明了,有机会我会继续总结一番的

《UNIX教程》读书笔记(一)

《UNIX教程》读书笔记

Part I    UNIX Shell

1 文件类型

  • d 目录。
  • l 符号链接(指向另一个文件)。
  • s 套接字文件。
  • b 块设备文件。
  • c 字符设备文件。
  • p 命名管道文件。
  • - 普通文件,或者更准确地说,不属于以上几种类型的文件。

2 该变权限位
chmod命令的一般格式为:
    chmod [who] operator [permission] filename
w h o的含义是:
u 文件属主权限。
g 同组用户权限。
o 其他用户权限。
a 所有用户(文件属主、同组用户及其他用户)。
o p e r a t o r的含义:
+ 增加权限。
- 取消权限。
= 设定权限。
p e r m i s s i o n的含义:
r 读权限。
w 写权限。
x 执行权限。
s 文件属主和组s e t - I D。
t 粘性位*。
l 给文件加锁,使其他用户无法访问。
u,g,o 针对文件属主、同组用户及其他用户的操作。

chmod命令绝对模式的一般形式为:
chmod [mode] file
其中m o d e是一个八进制数。

3 目录
目录的读权限位意味着可以列出其中的内容。写权限位意味着可以在该目录中创建文件,如果不希望其他用户在你的目录中创建文件,可以取消相应的写权限位。执行权限位则意味着搜索和访问该目录。

如果把同组用户或其他用户针对某一目录的权限设置为- - x,那么他们将无法列出该目录中的文件。如果该目录中有一个执行位置位的脚本或程序,只要用户知道它的路径和文件名,仍然可以执行它。用户不能够进入该目录并不妨碍他的执行。

目录的权限将会覆盖该目录中文件的权限。

4 suid/guid
suid
意味着如果某个用户对属于自己的shell脚本设置了这种权限,那么其他用户在执行这一脚本时也会具有其属主的相应权限。于是,如果根用户的某一个脚本设
置了这样的权限,那么其他普通用户在执行它的期间也同样具有根用户的权限。同样的原则也适用于guid,执行相应脚本的用户将具有该文件所属用户组中用户
的权限。

有相当一些U N I X命令也设置了s u i d和g u i d。如果想找出这些命令,可以进入/ b i n或/ s b i n目
录,执行下面的命令:
$ ls -l | grep '^...s'
上面的命令是用来查找s u i d文件的;
$ ls -l | grep '^...s..s'
上面的命令是用来查找s u i d和g u i d的。

如果希望设置s u i d,那么就将相应的权限位之前的那一位设置为4;如果希望设置g u i d,那么就将相应的权限
位之前的那一位设置为2;如果希望两者都置位,那么将相应的权限位之前的那一位设置为4+2。
一旦设置了这一位,一个s将出现在x的位置上。记住:在设置s u i d或g u i d的同时,相应的
执行权限位必须要被设置。例如,如果希望设置g u i d,那么必须要让该用户组具有执行权限。
如果想要对文件l o g i n设置s u i d,它当前所具有的权限为rwx rw- r-- (741),需要在使用
c h m o d命令时在该权限数字的前面加上一个4,即chmod 4741,这将使该文件的权限变为rws
rw- r - -。
$ chmod 4741 logit

还可以使用符号方式来设置s u i d / g u i d。如果某个文件具有这样的权限: rwx r-x r- x,那么
可以这样设置其s u i d:
chmod u+s <filename>
于是该文件的权限将变为: rws r-x r-x
在查找设置了s u i d的文件时,没准会看到具有这样权限的文件:rwS r-x r- x,其中S为大写。
它表示相应的执行权限位并未被设置,这是一种没有什么用处的s u i d设置,可以忽略它的存在。

在改变一个文件的所有权时,相应的suid也将被清除,这是出于安全性的考虑。

5 chown和chgrp
chown命令的一般形式为:
    chmod -R -h owner file
-R选项意味着对所有子目录下的文件也都进行同样的操作。- h选项意味着在改变符号链接文件的属主时不影响该链接所指向的目标文件。
c h g r p命令和c h o w n命令的格式差不多.

如果你希望知道自己属于哪些用户组,可以用group或id命令。如果要查看其他用户所属于的组,可以用命令group XXX,XXX是某个用户名。

6 umask
umask命令确定了你创建文件的缺省模式.一般来说,u m a s k命令是在/ e t c / p r o f i l e文件中设置的,每个用户在登录时都会引用这个文
件,所以如果希望改变所有用户的u m a s k,可以在该文件中加入相应的条目。如果希望永久性
地设置自己的u m a s k值,那么就把它放在自己$ H O M E目录下的. p r o f i l e或. b a s h _ p r o f i l e文件中。

表1-8 umask值与权限
umask     文件    目录
0             6         7
1             6         6
2             4         5
3             4         4
4             2         3
5             2         2
6             0         1
7             0         0

7 符号链接(软连接)
该命令的一般形式为:
ln [-s] source_path target_path
其中的路径可以是目录也可以是文件。

8 find命令
find命令的一般形式为:
    find pathname -options [-print -exec -ok]

让我们来看看该命令的参数:
pathname find命令所查找的目录路径。例如用.来表示当前目录,用/来表示系统根目录。
-print find命令将匹配的文件输出到标准输出。
-exec find命令对匹配的文件执行该参数所给出的s h e l l命令。相应命令的形式为' command' {} /;,注意{ }和/;之间的空格。
-ok 和- exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,
在执行每一个命令之前,都会给出提示,让用户来确定是否执行。

find命令有很多选项或表达式,每一个选项前面跟随一个横杠-。
    -name 按照文件名查找文件。
    -perm 按照文件权限来查找文件。在使用这一选项的时候,最好使用八进制的权限表示法。$ find . -perm 755 -print
    -prune 使用这一选项可以使f i n d命令不在当前指定的目录中查找,如果同时使用了-depth选项,那么-prune选项将被find命令忽略。
    -user 按照文件属主来查找文件。
    -group 按照文件所属的组来查找文件。
    -mtime
-n +n 按照文件的更改时间来查找文件, - n表示文件更改时间距现在n天以内,+
n表示文件更改时间距现在n天以前。Find命令还有-atime和-ctime选项,但它们都和-mtime选项相似,所以我们在这里只介绍
-mtime选项。
    -nogroup 查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在。
    -nouser 查找无有效属主的文件,即该文件的属主在/etc/passwd中不存在。
    -newer file1 ! file2 查找更改时间比文件f i l e 1新但比文件f i l e 2旧的文件。
    -type 查找某一类型的文件,诸如:
        b - 块设备文件。
        d - 目录。
        c - 字符设备文件。
        p - 管道文件。
        l - 符号链接文件。
        f - 普通文件。
    -size n[c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计。
    -depth 在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。
    -fstype 查找位于某一类型文件系统中的文件,这些文件系统类型通常可以在配置文件/etc/fstab中找到,该配置文件中包含了本系统中有关文件系统的信息。
    -mount 在查找文件时不跨越文件系统m o u n t点。
    -follow 如果f i n d命令遇到符号链接文件,就跟踪至链接所指向的文件。
    -cpio 对匹配的文件使用c p i o命令,将这些文件备份到磁带设备中。

Fedora 9安装星际译王(stardict)

Fedora 9安装星际译王(stardict)

一直苦于Linux下没有好用的翻译软件,一直再用Google的在线辞典,感觉还好。但Google在线词典最大的问题就是不能屏幕取词,而且用起来也不怎么方便,于是下决心找到一款比较好的翻译软件。

Google了一下,发现了星际译王的口碑不错,于是去http://stardict.sourceforge.net/cn/download.php 上下了一个rpm安装包,结果安装时报错:

rpm -ivh stardict-3.0.1-1.fc8.i386.rpm
error: Failed dependencies:
        espeak is needed by stardict-3.0.1-1.fc8.i386
        libespeak.so.1 is needed by stardict-3.0.1-1.fc8.i386

又下了.bz2的安装包,./configure时有N多错误。幼小的心灵倍受打击,深感国产Linux软件之不专业。

正郁闷之时,忽见网上有人说用yum安装。于是打开终端输入 yum install stardict,没想到竟然成功安装了!根本不需要特殊配置。

然后又下载了可用于星际译王的朗道英汉、汉英辞典,rpm安装,一切顺利。

试着在终端敲入 stardict运行了一下,界面很漂亮,效果很不错。顿时感觉国产开源软件还是有希望的。

谢谢胡正等前辈!

CDMA2000 Channel Naming Conventions

CDMA2000 Channel Naming Conventions

 Many
cdma2000 standards refer to logical channels, physical channels, or
both. The following naming conventions apply to all cdma2000 standards.

 1 Logical Channel Naming Convention
 A logical channel name consists of three lower case letters followed by “ch” (channel). A hyphen is
 used after the first letter. Table 1Table 1shows the naming conventions for the logical channels that
 are used in this family of standards.

 Table 1. Naming Conventions for Logical Channels
    First Letter        Second Letter         Third letter
    f = Forward       d = Dedicated         t = Traffic
    r = Reverse        c = Common        s = Signaling

 For example, the logical channel name for the Forward Dedicated Traffic Channel is f-dtch.

2 Physical Channel Naming Convention
 Physical channels are represented by upper case abbreviations. As in the case of logical channels,
 the first letters in the names of the channels indicate the direction of the channel (i.e., forward or
 reverse) and is followed by a hyphen. Table 2Table 2 shows the names and meanings of all the
 physical channels designated in cdma2000.

Table 2. Physical Channel Names
    Channel Name1            Physical Channel
    F/R-FCH                 Forward/Reverse Fundamental Channel
    F/R-DCCH               Forward/Reverse Dedicated Control Channel
    F/R-SCCH               Forward/Reverse Supplemental Code Channel
    F/R-SCH                 Forward/Reverse Supplemental Channel
    F-PCH                     Paging Channel
    F-QPCH                 Quick Paging Channel
    R-ACH                     Access Channel
    F/R-CCCH               Forward/Reverse Common Control Channel
    F/R-PICH                 Forward/Reverse Pilot Channel
    F-APICH                 Dedicated Auxiliary Pilot Channel
    F-TDPICH                 Transmit Diversity Pilot Channel
    F-ATDPICH             Auxiliary Transmit Diversity Pilot Channel
    F-SYNCH                 Sync Channel
    F-CPCCH                 Common Power Control Channel
    F-CACH                 Common Assignment Channel
    R-EACH                 Enhanced Access Channel
    F-BCCH                 Broadcast Control Channel
    F-PDCH                 Forward Packet Date Channel
    F-PDCCH                 Forward Packet Data Control Channel
    R-ACKCH                 Reverse Acknowledgement Channel
    R-CQICH                 Reverse Channel Quality Indicator Channel
    F-ACKCH                 Forward Acknowledgement Channel
    F-GCH                     Forward Grant Channel
    F-RCCH                 Forward Rate Control Channel
    R-PDCH                 Reverse Packet Data Channel
    R-PDCCH                 Reverse Packet Data Control Channel
    R-REQCH                 Reverse Request Channel

1 The notations “F/R” and “Forward/Reverse” represent two different
physical channels (i.e., one forward channel and one reverse
channel)

For example, the physical channel name for the Forward Fundamental Channel is F-FCH.

References:
 3GPP2 C.S0001-D v2.0

《Advanced Programming in the UNIX Environment》读书笔记(2)

8UNIX Standards

·       ISO C

            In late 1989, ANSI Standard X3.1591989 for the C programming language was approved. This standard has also been adopted as international standard ISO/IEC 9899:1990.             In 1999, the ISO C standard was updated and approved as ISO/IEC 9899:1999, largely to improve support for applications that perform numerical processing.


·       IEEE POSIX


·       ISO/IEC 9945-1 (IEEE Standard 1003.1-1996), which includes

                   IEEE Standard 1003.1-1990                    IEEE Standard 1003.1b-1993 (real-time extensions)                    IEEE Standard 1003.1c-1995 (pthreads)                    IEEE Standard 1003.1i-1995 (real-time technical corrigenda)

·       IEEE P1003.1a draft standard (system interface revision)

·       IEEE Standard 1003.1d-1999 (advanced real-time extensions)

·       IEEE Standard 1003.1j-2000 (more advanced real-time extensions)

·       IEEE Standard 1003.1q-2000 (tracing)

·       IEEE Standard 1003.2d-1994 (batch extensions)

·       IEEE P1003.2b draft standard (additional utilities)

·       Parts of IEEE Standard 1003.1g-2000 (protocol-independent interfaces)

·       ISO/IEC 9945-2 (IEEE Standard 1003.2-1993)

·       The Base Specifications of the Single UNIX Specification, version 2, which include

·      System Interface Definitions, Issue 5

·      Commands and Utilities, Issue 5

·      System Interfaces and Headers, Issue 5

·       Open Group Technical Standard, Networking Services, Issue 5.2

·       ISO/IEC 9899:1999, Programming Languages - C




·       The Single UNIX Specification


              A superset of the POSIX.1 standard, specifies additional interfaces that extend the functionality provided by the basic POSIX.1 specification.


·       FIPS


        


9The header <sys/types.h> defines some implementation-dependent data types, called theprimitive system data types. More of these data types are defined in other headers also. These data types are defined in the headers with the C typedef facility. Most end in _t.                   Figure 2.20. Some common primitive system data types              Type                                                       Description caddr_t                     core address (Section 14.9) clock_t                     counter of clock ticks (process time) (Section 1.10) comp_t                      compressed clock ticks (Section 8.14) dev_t                       device numbers (major and minor) (Section 4.23) fd_set                      file descriptor sets (Section 14.5.1) fpos_t                      file position (Section 5.10) gid_t                       numeric group IDs ino_t                       i-node numbers (Section 4.14) mode_t                      file type, file creation mode ( ection 4.5)                                                           S nlink_t                     link counts for directory entries (Section 4.14) off_t                       file sizes and offsets (signed) (seek, Section 3.6)                                                              l pid_t                       process IDs and process group IDs (signed) ( ections 8.2 and 9.4)                                                                              S ptrdiff_t                   result of subtracting two pointers (signed) rlim_t                      resource limits (Section 7.11) sig_atomic_t                data type that can be accessed atomically ( ection 10.15)                                                                           S sigset_t                    signal set (Section 10.11) size_t                      sizes of objects (such as strings) (unsigned) ( ection 3.7)                                                                             S ssize_t                     functions that return a count of bytes (signed) (ead, write, Section 3.7)                                                                               r time_t                      counter of seconds of calendar time (Section 1.10) uid_t                       numeric user IDs wchar_t                   can represent all distinct character codes 10 Conflicts Between Standards     ISO C defines the function clock to return the amount of CPU time used by a process. The value returned is a value. To convert this value to seconds, we divide it by CLOCKS_PER_SEC, which is defined in the<time.h> header. POSIX.1 defines clock_t the function times that returns both the CPU time (for the caller and all its terminated children) and the clock time. All these time values are clock_t values. The sysconf function is used to obtain the number of clock ticks per second for use with the return values from the  times function. What we have is the same term, clock ticks per second, defined differently by ISO C and POSIX.1. Both standards also use the same data type (clock_t ) to hold these different values. The difference can be seen in Solaris, whereclock returns microseconds (hence CLOCKS_PER_SEC is 1 million), whereassysyconf returns the value 100 for clock ticks per second.     Another area of potential conflict is when the ISO C standard specifies a function, but doesn't specify it as strongly as POSIX.1 does. This is the case for functions that require a different implementation in a POSIX environment (with multiple processes) than in an ISO C environment (where very little can be assumed about the host operating system). Nevertheless, many POSIX-compliant systems implement the ISO C function, for compatibility. The signal function is an example. If we unknowingly use thesignal function provided by Solaris (hoping to write portable code that can be run in ISO C environments and under older UNIX systems), it'll provide semantics different from the POSIX.1 sigaction function. 11 Most file I/O on a UNIX system can be performed using only five functions: open, read, write, lseek, and close.They're are often referred to as unbuffered I/O, in contrast to the standard I/O routines. The term unbuffered means that each read or write invokes a system call in the kernel. These unbuffered I/O functions are not part of ISO C, but are part of POSIX.1 and the Single UNIX Specification. 12 File Descriptors

    To the kernel, all open files are referred to by file descriptors. A file descriptor is a non-negative integer. When we open an existing file or create a new file, the kernel returns a file descriptor to the process. When we want to read or write a file, we identify the file with the file descriptor that was returned by open or creat as an argument to either read or write.

    By convention, UNIX System shells associate file descriptor 0 with the standard input of a process, file descriptor 1 with the standard output, and file descriptor 2 with the standard error. This convention is used by the shells and many applications; it is not a feature of the UNIX kernel.

   The magic numbers 0, 1, and 2 should be replaced in POSIX-compliant applications with the symbolic constants STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO. These constants are defined in the <unistd.h> header.

 

13

    (1) open Function

      A file is opened or created by calling the open function.

 

[View full width]

#include <fcntl.h>

int open(const char *pathname, int oflag, ... /*

 mode_t mode   */ );

 

Returns: file descriptor if OK, 1 on error

    (2) creat Function

    A new file can also be created by calling the creat function.

 

#include <fcntl.h>

int creat(const char *pathname, mode_t mode);

 

Returns: file descriptor opened for write-only if OK, 1 on error

 

    Note that this function is equivalent to

    open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);

    (3) close Function

    An open file is closed by calling the close function.

 

#include <unistd.h>

int close(int filedes);

 

Returns: 0 if OK, 1 on error

        (4) lseek Function

 

#include <unistd.h>

off_t lseek(int filedes, off_t offset, int whence);

 

Returns: new file offset if OK, 1 on error

    (5) read Function

    Data is read from an open file with the read function.

 

#include <unistd.h>

ssize_t read(int filedes, void *buf, size_t nbytes);

 

Returns: number of bytes read, 0 if end of file, 1 on error

    (6) write Function

    Data is written to an open file with the write function.

 

[View full width]

#include <unistd.h>

ssize_t write(int filedes, const void *buf, size_t

 nbytes);

 

Returns: number of bytes written if OK, 1 on error

《Advanced Programming in the UNIX Environment》读书笔记(1)

1、系统口令文件通常为/etc/passwd。口令文件中的登录项由7个以冒号分隔的字段组成:登录名、加密口令、数字用户ID、数字组 ID、注释字段、起始目录以及shell程序。

2、不能出现在文件名中的字符只有两个:/和空操作符(null)。

    当创建一个新目录时,自动创建了两个文件名:.和..。.引用当前目录,..引用父目录。

     A process can change its working directory with the chdir function.

3、ls(1)用以引用UNIX手册集中的一个特定项,它引用第一部分中的ls项。各部分通常用数字1~8表示,在每个部分中的各项则按字母顺序排列。

4、UNIX目录操作函数:opendir, readdir, closedir。
    三个用于进程控制的主要函数:fork, exec, waitpid。
5、头文件<unistd.h>中包含了许多UNIX系统服务的函数原型,函数原型是ANSI C标准的组成部分。
6、当度量一个进程的执行时间时,UNIX系统使用三个进程时间值:

  • 时钟时间
  • 用户CPU时间
  • 系统CPU时间 

    时钟时间又称为墙上时钟时间(wall clock time),是进程运行的时间总量,其值与系统中同时运行的进程数有关。
    用户CPU时间是执行用户指令所用的时间量。
    系统CPU时间是为该进程执行内核所经历的时间。
    用户CPU时间 和 系统CPU时间的被称为CPU时间。
    要取得任一进程的时钟时间、用户时间和系统时间很简单,只需执行命令time(1), 其参数是要度量其执行时间的命令。如:
[bonn@localhost unix_advance]$ time ps
  PID TTY          TIME CMD
 3734 pts/2    00:00:00 bash
 6743 pts/2    00:00:00 ps

real    0m0.023s
user    0m0.010s
sys    0m0.013s

7、BSD: the Berkeley Software Distribution

开源授权协议

[说明]:本文摘自《程序员》2008年06月刊许洪波教授的《开源授权协议(License)初探》一文,版权归原作者所有。


1OSI(www.opensource.org)是目前世界上针对开源软件授权进行认证的唯一机构。

2、开源软件的特点:

  • 免费的再发布:软件授权拥有者必须允许,包括软件的获得者和使用者将软件重新分发给其他人,而不向版权的拥有者支付版权相关的费用。

  • 源代码的访问:开源授权需要提供源代码。

  • 衍生作品:授权必须允许使用者修改软件,并在其基础上做出创新工作。授权必须允许这些修改和衍生作品在和原来的软件版权条件相同下发布。

  • 杜绝歧视:只要遵守开源许可版权,人人都可以使用开源软件;同时,开源软件版权不得限制任何人在特定领域使用该软件。

3、开源授权模式:

1)强开源约束授权——GNU GPL。基于GPL的任何软件及衍生应用程序,其源代码必须公开,并不得因此收费。

2)弱开源约束授权——Mozilla公用授权(MPL)和LGPLMPL协议要求假如你修改了一个基于MPL协议的源代码,则必须列入或公开你所做的修改。假如你的软件采用了基于LGPL的开源软件,LGPL要求任何针对LGPL开源软件的修改必须公开其源代码,但不要求基于源代码之上的衍生应用开放其源代码。

3)无开源约束授权——BSD授权协议。BSD几乎允许用户做任何他们想要想要在BSD的授权代码上做的事情;他们也可以将软件用于免费或商业目的;他们也可以发布或不发布变更后的源代码。BSD的唯一要求就是软件使用者声明他们使用了软件原作者的著作权。

(4)其他开源授权。