Chinaunix首页 | 论坛 | 博客
  • 博客访问: 501300
  • 博文数量: 174
  • 博客积分: 8001
  • 博客等级: 中将
  • 技术积分: 1840
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-04 19:30
文章分类

全部博文(174)

文章存档

2011年(1)

2010年(24)

2009年(149)

我的朋友

分类: LINUX

2009-05-10 21:23:05

Linux上的C编程。
首先考虑的如果是编程环境的话,那么是VIM+GCC+GDB,但是由于现在还是在写“HELLO, WORLD“的阶段,所以CSCOPE之类的工具,作为VIM的IDE补充,并没有发挥用途。说到VIM,必须考虑到我的哲学,就是:
如果事先准备好可以使用的东西,并且在以后的实践中使用,那么就容易的养成了习惯。
所以一开始不遗余力的学习VIM编辑器。但是现在貌似有很多的丢掉了。需要总结一下,但是在这里就只讨论Linux编程。
暂时不涉及GUI,也不讲内核,驱动程序,只是讨论一般的应用程序如何使用系统调用,包括网络应用。就我知道的水平来说,认为LINUX可以按照功能模块来划分,讨论以下:
1.LINUX I/O (包括文件,SOCKET)
2.LINUX 多线程/进程
 
Linux文件系统的基本方面就是统一的文件抽象,使用OPEN, CLOSE,WRITE和READ,那么面向的是文件描述符fid,而不是C库函数的fopen等,面向文件句柄(使用这些是可以的,两者是可以相互转换的)。使用stat可以获得文件信息。Linux的一个优越的地方时统一的文件抽象,无论是块设备, 字符设备,磁盘文件,SOCKET,管道等,当然对于不涉及设备的目前阶段而言,这个优越之处没有多大体现。anyway, 欣赏Linux继承自UNIX的哲学体系。
 
Linux SOCKET编程包括TCP和UDP端口,有一系列的函数和规范提供支持,套用这些规范,使用这些函数,能够写出简单的应用程序。Well, 我必须说,事情事实上没有这么简单。因为在前面提到文件的时候,我没有提到一个很重要的概念,那就是阻塞。
 
当你向一个端口或者设备写数据的时候,可能因为缓冲区满的关系,你必须等待缓冲区有新的空间;当你从一个端口或者设备读数据的时候,你也可能因为没有新的数据而必须等待。你可以选择阻塞,通常是BLOCK,或者不阻塞的标记NOBLOCK,这是由统一文件抽象提供的行为描述,我们称为I/O模型,它包括:
1.阻塞式I/O
2.非阻塞式I/O
3.多路复用I/O
4.信号驱动I/O
如果是阻塞式I/O,对于慢系统调用(通常和慢设备相关),如果一个信号处理程序引起了EINTR错误返回,那么应用程序只需要检查EINTR错误并重新读写。
不把常规文件当作慢设备。(这是否意味着常规文件不需要检查EINTR错误?)
如果是非阻塞式I/O,除了处理EINTR,还要处理EAGAIN(在有些系统上,称之为EWOULDBLOCK)。
处理EAGAIN的方式通常也是简单的重新读写。
 
对于EINTR和EAGAIN的处理方法貌似稍有不同,但是在这里的例子事实上,可以发现事实上一样的结果。

int readn(int fd,void *vptr,int n)
{
    int nleft,nread;
    char *ptr;

    ptr =vptr;
    nleft =n;
    while(nleft>0)
    {
        if((nread = read(fd,ptr,nleft)) < 0 )
        {
            if(errno == EINTR)

                nread = 0;
            else if(errno == EWOULDBLOCK)
                continue;
            else
                return -1;
        }else if(nread == 0) /* EOF */
            break;
        nleft -= nread;
        ptr += nread;
    }
    return (n-nleft);
}

其他两种I/O方式先不讨论。

另外,mmap的方式被视为高级I/O,是实践之中非常有用的手段,避免了慢的I/O操作。


LINUX多线程/进程,是一个广泛的问题。在OS课程里,我们知道了OS其实最核心的东西只有两个:THREADS & RESOURCE。也就是说,OS核心的是执行引擎(由于进程的概念不是独立的,这里不讨论)和资源分配。I/O事实上,是资源分配的问题,EAGAIN代表Resource temporarily unavailable,意思是说现在的资源暂时不够用; EINTR代表 Interrupted function call,意思是说慢系统调用被信号处理中断了,也就是说这个系统调用的线程的上下文被切换到了信号处理程序。

首先我们知道了pthread_create和fork等一系列基本的线程/进程处理函数,并且了解了线程和进程的区别和联系(参考我前面写过的进程 & 线程一文,这里重申:

进程是资源管理的最小单元;而线程是程序执行的最小单元。一个进程的组成实体可以分为两大部分:线程集合和资源集合。进程中的线程是动态的对象;代表了进程指令的执行。资源,包括地址空间、打开的文件、用户信息等等,由进程内的线程共享。线程有自己的私有数据:程序计数器,栈空间以及寄存器(可以认为线程自己保存着CPU的状态,而和其他线程共享内存空间)。

多进程环境下,进程之间常常需要协调。例如一个处理数据的进程处理好数据后,需要通知另一个进程来接受这些数据。而在处理好之前,另一个进程不应该访问这些数据,因为它们是原始的而不具备意义的。

我不适用同步这个术语,而使用协调这个术语,是因为同步往往指的是多个进程访问同一个资源时的措施,它保证了一个有序的机制,但它并不是预先规定的有序步骤。而协调是指,多个进程需要彼此的工作按照预先规定的的有序步骤进行。

我们先讨论一个重要的协调进制,信号。信号在进程协调之间的重要作用是无疑的。相关的实现和代码以后补充,值得注意的是,信号一般式针对进程而言的,但是作为重要的补充,也有针对线程的信号函数。有时候,使用多线程来完成某些工作会更加方便一些(但绝对不是必要的)。

关于LINUX进程之间通信的手段,就是管道和FIFO。信号也是进程之间通信的手段,它是异步的,被视为软件中断。

LINUX进程之间通信的手段还包括XIPC,即信号灯,共享内存,消息。

其中信号灯可以实现OS课程里提到的避免死锁的机制。

阅读(1143) | 评论(0) | 转发(0) |
0

上一篇:about google calendar

下一篇:GStreamer and TI

给主人留下些什么吧!~~