| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2519 人关注过本帖
标题:【求助】C标准库一书中的“原语”一词求解释【共同学习】
只看楼主 加入收藏
c10121209
Rank: 1
等 级:新手上路
帖 子:18
专家分:5
注 册:2013-1-25
结帖率:100%
收藏
 问题点数:0 回复次数:15 
【求助】C标准库一书中的“原语”一词求解释【共同学习】
最近再看《C标准库》这本书,感觉里面的知识真是晦涩难懂。
       我有一个想法,按照书中给出的代码把stdio这个库自己写一遍,加深理解。但是发现书中提到的底层原语一词不是很明白。

       我理解的“原语”是标准库中底层真正去执行某一个动作的方法,或者说是接口,那么这种原语在不同的平台上是否就代表了操作系统的API呢?
        怎么在自己写的库中调用这种原语,我用的是VS2008。如果哪位大神能给小弟提供个具体编写的方法(在我的编译器上),小弟跪谢了。

        百度百科中的原语解释:
        原语通常由若干条指令组成,用来实现某个特定的操作。通过一段不可分割的或不可中断的程序实现其功能。
        
        求大神给我讲讲stdio这个库 中的层次关系 和 与操作系统 间的联系。。。。。

        祝大家 新年快乐!
搜索更多相关主题的帖子: 百度百科 编译器 接口 
2013-01-25 11:23
c10121209
Rank: 1
等 级:新手上路
帖 子:18
专家分:5
注 册:2013-1-25
收藏
得分:0 
求顶啊,求大神啊。若小弟真的搞明白了,会以总结帖的形式发出,服务大众。。。。
2013-01-25 11:26
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
问得好深啊。。
2013-01-25 12:15
c10121209
Rank: 1
等 级:新手上路
帖 子:18
专家分:5
注 册:2013-1-25
收藏
得分:0 
看了一下午,发现我的编译器vs2008中,<io.h> 算是最接近底层的接口了,那么所谓的原语就是它了吧。
在fopen(...)这个方法中 我的编译器分别调用了 _getstream()<internal.h> 和 _open()<io.h> 来获取流和打开文件。
2013-01-25 14:56
meiyounichen
Rank: 2
等 级:论坛游民
威 望:1
帖 子:35
专家分:29
注 册:2012-12-31
收藏
得分:0 
回复 楼主 c10121209
kk

[ 本帖最后由 meiyounichen 于 2013-1-26 15:23 编辑 ]
2013-01-25 15:44
c10121209
Rank: 1
等 级:新手上路
帖 子:18
专家分:5
注 册:2013-1-25
收藏
得分:0 
你加我吧 1144920065 我公司上班时间不让上秋秋。
2013-01-25 16:31
c10121209
Rank: 1
等 级:新手上路
帖 子:18
专家分:5
注 册:2013-1-25
收藏
得分:0 
程序代码:
/***
*stream.c - 查找一个未使用的流
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*目的:
*       定义 _getstream() - 查找一个未使用的流
*
*******************************************************************************/

#include <cruntime.h>
#include <windows.h>
#include <malloc.h>
#include <stdio.h>
#include <file2.h>
#include <internal.h>
#include <mtdll.h>
#include <dbgint.h>

/***
*FILE *_getstream() - 查找一个未使用的流
*
*目的:
*       查找一个未使用的流并使其对调用者有效。 此函数打算只在库内使用。
*
*进入:
*       无参数. 扫描 __piob[]
*
*退出:
*       返回指向空闲流的指针, 或者 NULL 如果都已被使用.
        一个流成为被指定的状态,如果调用者决定使用 r w r/w 中的任意模式。
*
*       [多线程主意: 如果找到一个空闲流, 它被已锁住的状态返回.  解锁这个流是调用者的责任.]
*
*Exceptions:
*
*******************************************************************************/

FILE* _getstream ()
{
    FILE* retval = NULL;                                                           //定义返回值
    int i;

    /* Get the iob[] scan lock */
    _mlock(_IOB_SCAN_LOCK);                                                        //<mtdll.h> void _lock(int); 请求线程锁 _IOB_SCAN_LOCK锁ID 用于扫描存储流的表
    __try {

        /*
        * 通过 __piob 表循环查找一个空闲流, 或一个NULL结果.
        */
        for ( i = 0 ; i < _nstream ; i++ ) {                                       //<internal.h> _nstream(_NSTREAM_  512) 打开文件的最大数量

            if ( __piob[i] != NULL ) {                                             //<internal.h> void** __piob; 指向保存FILE资源地址的表的表头指针 推测:__iob[]的类型为 FILE* __iob[_nstream];
                /*
                * 判断如果流未在使用中,则返回此流.
                */
                if ( !inuse( (FILE *)__piob[i] ) && !str_locked( (FILE *)__piob[i] ) ) {
                    //<file2.h> #define inuse(s) ((s)->_flag & (_IOREAD | _IOWTITE | _IORW))
                    //<file2.h> #define str_locked ((s)->_flag & (_IOLOCKED))
                    //若流的当前状态不是 只读 只写 可读可写 锁定 则表达式为真
                    /*
                    * Allocate the FILE lock, in case it hasn't already been
                    * allocated (only necessary for the first _IOB_ENTRIES
                    * locks, not including stdin/stdout/stderr).  Return
                    * failure if lock can't be allocated.
                    */
                    if ( i > 2 && i < _IOB_ENTRIES )                               //流的下标大于2,小于_IOB_ENTRIES(20)
                        if ( !_mtinitlocknum( _STREAM_LOCKS + i ) )                //<mtdll.h> int _mtinitlocknum(int); 给出空闲ID号,分配一个新的,非预先分配的线程锁。失败返回0。
//#define _STREAM_LOCKS   16      /* 流的线程锁起始ID */
//#define _LAST_STREAM_LOCK  (_STREAM_LOCKS+_IOB_ENTRIES-1) /* 最后一个线程锁ID */
//#define _TOTAL_LOCKS        (_LAST_STREAM_LOCK+1)
                            break;

                    _lock_str2(i, __piob[i]);                                      //<mtdll.h> void _lock_file2(int, void*); 用新分配的线程锁_STREAM_LOCKS + i锁定文件__piob[i],在他的内部调用的是_lock。

                    if ( inuse( (FILE *)__piob[i] ) ) {
                        _unlock_str2(i, __piob[i]);                                //<mtdll.h> void _unlock_file2(int, void*); 解锁文件,内部调用_unlock。
                        continue;                                                  //若文件已经在使用中,则接着扫描。(不明其用意)
                    }
                    retval = (FILE *)__piob[i];                                    //赋值给返回值
                    break;
                }
            }
            else {                                                                 //预先准备的流资源数量为20,超过20执行下面的操作。
                /*
                * 将_piob[i]设置为新分配的_FILEX资源, 并返回指向它的指针.
                * 下面的操作进入windows底层。C标准规定同时打开文件的数量至少为8,
                * 如果打开超过20就要依靠window底层API调用,那么就没有可移植性了。
                */
                if ( (__piob[i] = _malloc_crt( sizeof(_FILEX) )) != NULL ) {

                    if ( !__crtInitCritSecAndSpinCount(
                        &(((_FILEX *)__piob[i])->lock), _CRT_SPINCOUNT ))
                    {
                        /*
                        * Failed to initialize the critical section because
                        * of lack of memory, clean up and return failure.
                        */
                        _free_crt( __piob[i] );
                        __piob[i] = NULL;
                        break;
                    }

                    EnterCriticalSection( &(((_FILEX *)__piob[i])->lock) );
                    retval = (FILE *)__piob[i];
                    retval->_flag = 0;
                }

                break;
            }
        }

        /*
        * 配置这个返回流的信息。.
        */
        if ( retval != NULL ) {
            /* 确保 _IOLOCKED 是预制的并且其他状态位为0 */
            retval->_flag &= _IOLOCKED;
            retval->_cnt = 0;
            retval->_tmpfname = retval->_ptr = retval->_base = NULL;
            retval->_file = -1;                                                        //文件描述符,此流未与任何的文件建立联系。
        }

    }
    __finally {
        _munlock(_IOB_SCAN_LOCK);                                                      //<mtdll.h> void _unlock(int); 释放线程锁 _IOB_SCAN_LOCK锁ID
    }

    return(retval);                                                                    //返回流资源的地址或NULL。
}
尝试解读了一遍_getstream(...)这个函数,求指正,看看我那里理解的不对。

如果自己实现这个方法,不知道线程锁那个地方有什么好的替换函数没有?

[ 本帖最后由 c10121209 于 2013-1-25 22:34 编辑 ]
2013-01-25 22:32
c10121209
Rank: 1
等 级:新手上路
帖 子:18
专家分:5
注 册:2013-1-25
收藏
得分:0 
当打开文件数量>=20,从 _iob[20] 中获得预先准备好的流资源。
当打开文件数量<20,则额外分配 _FILEX 结构体来产生新的流资源。
struct _FILEX
{
    FILE f;
    CRITICAL_SECTION lock;
};
_FILEX 封装了 "流f" 和 "临界区lock"。临界区用与流的线程保护。

找了一下临界区有关的API: <windows.h>

void InitializeCriticalSection(CRITICAL_SECTION*);      
初始化一个临界区。

void EnterCriticalSection(CRITICAL_SECTION*);
申请所有权,进入临界区。

void LeaveCriticalSection(CRITICAL_SECTION*);
移除所有权,离开临界区。

void DeleteCriticalSection(CRITICAL_SECTION*);
释放临界区资源。

临界区释放后不可以再以任何方法调用,也不可以释放一个被线程占用的临界区,会有错误产生。

推测:锁住 _iob[20] 用的是预先准备好临界区资源,而 _STREAM_LOCKS ~ _STREAM_LOCKS+19 就是它们在表中的ID了。
2013-01-26 10:02
meiyounichen
Rank: 2
等 级:论坛游民
威 望:1
帖 子:35
专家分:29
注 册:2012-12-31
收藏
得分:0 
kk

[ 本帖最后由 meiyounichen 于 2013-1-26 15:24 编辑 ]
2013-01-26 14:17
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
以下是引用meiyounichen在2013-1-26 14:17:51的发言:

进我群聊,你的分析有问题

群主这样就不好了 公开拉人 论坛怎么发展呢
2013-01-26 14:47
快速回复:【求助】C标准库一书中的“原语”一词求解释【共同学习】
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.048767 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved