C++怎么判断一个SOCKET有没有被创建?

2025-04-15 02:50:58
推荐回答(3个)
回答1:

    当开始运行时,核心将自己装入到绝对地址0x90000(576K; 1001,0000,0000,0000,0000),再将其后的2k字节装入到地址0x90200(576.5k; 1001,0000,0010,0000,0000)处,最后将核心的其余部分装入到0x10000(64k; 1,0000,0000,0000,0000).

It then loads the system at 0x10000, using BIOS interrupts. Thereafter it disables all interrupts, moves the system down to 0x0000, changes to protected mode, and calls the start of system. System then must RE-initialize the protected mode in it's own tables, and enable interrupts as needed. 
  
然后,关掉所有中断,把系统下移到0x0000(0k;0000,0000,0000,0000,0000)处,改变到保护模式,然后开始系统的运行.系统必须重新在保护模式下初始化自己的系统表格,并且打开所需的中断.

NOTE 1!  currently system is at most 8*65536(8*64k=512k; 1000,0000,0000,0000,0000) bytes long. This should be no problem, even in the future. I want to keep it simple. This 512 kB kernel size should be enough  - in fact more would mean we'd have to move not just these start-up routines,  but also do something about the cache-memory (block IO devices). The area left over in the lower 640 kB (0xA0000;1010,0000,0000,0000,0000)  is meant for these. No other memory is assumed to be "physical", ie all memory over 1Mb is demand-paging. All addresses under 1Mb are guaranteed to match their physical addresses. 

NOTE1 abouve is no longer valid in it's entirety. cache-memory is allocated above the 1Mb mark as well as below. Otherwise it is mainly correct. 

NOTE 2! The boot disk type must be set at compile-time, by setting the following equ. Having the boot-up procedure hunt for the right disk type is severe brain-damage. The loader has been made as simple as possible (had to, to get it in 512 bytes with the code to move to protected mode), and continuos read errors will result in a unbreakable loop. Reboot by hand. It loads pretty fast by getting whole sectors at a time whenever possible. 
| 1.44Mb disks: sectors = 18 
| 1.2Mb disks: 
| sectors = 15 
| 720kB disks: 
| sectors = 9 
**********************************************************************************************

.globl begtext, begdata, begbss, endtext, enddata, endbss 
.text 
begtext: 
.data 
begdata: 
.bss 
begbss: 
.text 

BOOTSEG = 0x07c0            
|把第一个扇区装入到此处
INITSEG = 0x9000            
|核心装入地址的段地址  
SYSSEG  = 0x1000                           
|system loaded at 0x10000 (65536). 
ENDSEG  = SYSSEG + SYSSIZE      
|SYSSIZE在Makefile中定义的 ^_^ 

entry start 
start: 
        mov     ax,#BOOTSEG                
| BOOTSEG = 0x07C0;现在应仍处在REAL MODE下. 
        mov     ds,ax                       
| 移动自身从BOOTSEG:0000到INITSEG:0000 
        mov     ax,#INITSEG           
| 共512字节. 
        mov     es,ax                    
| 那么BOOT.S处在0x90000-0x90200. 
        mov     cx,#256 
        sub     si,si               
| 寄存器清零
        sub     di,di           
| 寄存器清零
        rep                  
        movw                 

| 将由SI作为指针的源串中的一个字节或字或双字传送到由DI作为指针的目的串中,并根据标志DF值自动修
| 改这两个指针以指向串中下一项。若带有前缀REP,则重复执行这一传送,直到CX寄存器等于零为止。
| 源地址:DS=0x07C0(31K;0111,1100,0000,0000);
| 目的地址:ES=0x9000(576K;1001,0000,0000,0000,0000)
| 小结:BIOS将启动盘的第一个扇区调入到0x07C00处,然后系统把自己从0x07C00处移动到0x90000-
| 0x90200处.

        jmpi    go,INITSEG 
go:  mov     ax,cs  
        mov     ds,ax                
      mov     es,ax               
| 将DS,ES,SS均设为0x9000,所有数据都以
| 0x9000为段偏移. 
        mov     ss,ax                
| 堆栈偏移0x9000 
        mov     sp,#0x400       
| 栈顶指针0x9000:0x0400,堆栈空间512bytes?? 

        mov     ah,#0x03        
| read cursor pos 
        xor     bh,bh 
        int     0x10 

        mov     cx,#24 
        mov     bx,#0x0007     
| page 0, attribute 7 (normal) 
        mov     bp,#msg1         
| 显示Loading System ... 
        mov     ax,#0x1301     
| write string, move cursor 
        int     0x10 

| ok, we've written the message, now 
| we want to load the system (at 0x10000)  
| 我们已经完成了“Loading...”的在屏幕上显示,
| 以下我们将完成把核心从0x10000(64k)移到0x01000(4k)处.

        mov     ax,#SYSSEG    
| SYSSEG  = 0x1000
        mov     es,ax              
| segment of 0x010000 
        call    read_it          
| 读内核到0x10000 
        call    kill_motor    
| 杀了软驱!? ^_^ 

| if the read went well we get current cursor position ans save it for 
| posterity. 

        mov     ah,#0x03          
| read cursor pos 
        xor     bh,bh 
        int     0x10                
| save it in known place, con_init fetches 
        mov     [510],dx          
| it from 0x90510(1001,0000,0101,0001,0000). 

| 功能03H,读取光标位置和类型。AH=03H,BH=页号。
| 返回:DH=当前字符行号;    DL=当前字符列号
|       CH=光标的起始光栅线;CL=光标的终止光栅线

| now we want to move to protected mode ... 

        cli                          
| 关掉所有中断
| first we move the system to it's rightful place 

        mov     ax,#0x0000 
        cld                                  
| 'direction'=0, movs moves forward 
do_move:  
        mov     es,ax                  
| ES=0x0000;destination segment 
        add     ax,#0x1000     
        cmp     ax,#0x9000 
        jz      end_move 
        mov     ds,ax                  
| DS=0x1000;source segment 
        sub     di,di               
| 置零,地址为0x1000:0000 
        sub     si,si                  
| 置零,地址为0x9000:0000 
        mov     cx,#0x8000       
| cx的作用是计数器,共0x8000=32k 
        rep 
        movsw 
        j       do_move                
| 将位于低端0x1000:0000的内核移到内存 
| 高端0x9000:0000,覆盖了boot.S !? 

| then we load the segment descriptors 

end_move: 

        mov     ax,cs           
| right, forgot this at first. didn't work :-) 
        mov     ds,ax 
        lidt    idt_48          
| idt_48和gdt_48都是一个3个word长的数据结构 
        lgdt    gdt_48          
| 第一个字说明(Global || Interrupt) Descriptor 
| Table有多长,因为每个Table是四个字长,所以 
| 可以得出整个DescriptorTable的entries.(见下) 
| 后两个字指出DT的具体位置. 
| idt_48是0,0,0;应表示没有中断描述符entries. 
| gdt_48有256个入口,第一个是个空入口,然后 
| 定义了一个code段和一个data段.基址都是 
| 0x00000000, !?那里是什么东西??? 
| *** 0x00000000 != 0x0000:0000 *** 

| that was painless, now we enable A20 

        call    empty_8042 
        mov     al,#0xD1                
| command write 
        out     #0x64,al 
        call    empty_8042 
        mov     al,#0xDF                
| A20 on 
        out     #0x60,al 
        call    empty_8042 

| well, that went ok, I hope. Now we have to reprogram the interrupts :-( 
| we put them right after the intel-reserved hardware interrupts, at 
| int 0x20-0x2F. There they won't mess up anything. Sadly IBM really 
| messed this up with the original PC, and they haven't been able to 
| rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, 
| which is used for the internal hardware interrupts as well. We just 
| have to reprogram the 8259's, and it isn't fun. 
| 初始化中断处理器8259i 
| 初始化顺序为:         1. 向主8259A写ICW1, 0x20 
|                       2. 向第二块8259A写ICW1, 0xA0 
|                       3. 向主8259A写ICW2, 0x21 
|                       4. 向第二块8259A写ICW2, 0xA1 
|                       5. 如果ICW1指示有级联中断处理器,则初始化Master&Slave 
|                       (在下例中只有IR2有级联8259A), 0x21, 0xA1 
|                       6. 向两块8259写ICW4,指定工作模式. 
| 输入了适当的初始化命令之后, 8259已经准备好接收中断请求. 
| 现在向他输入工作 
| 命令字以规定其工作方式.

回答2:

再顺带说一句,socket函数返回的是一个句柄,所以你的命名如果规范点 前面应该加上h也就是hClistSock以标明是个句柄

回答3:

判断ClistSock是不是INVALID_SOCKET