S:
运行fork的时候 函数会创建一个子进程 这个子进程会拷贝父进程的数据段 包括地址空间(页表) 而在老师后面的课程中讲到两个进程它们的地址空间是独立的 那我的疑问是: 既然子进程从父进程中拷贝了这个页表 虽然这两个页表是独立的 但是里面的内容不是相同的吗 那变量a存放的虚拟地址:-1354661604 通过这两个独立但内容相同的页表 所映射到实际物理内存不就相同了吗 难道子进程把拷贝过来的页表 又进行修改了下吗? 不理解
T:要是页表映射关系也相同,那进程地址空间就不是独立的了, 显然这种映射关系不会是纯粹的拷贝,而是分配了新的页表项
2.
S:
我看到vfork的实现 在相关的linux内核书里看到:它创建的进程能共享其父进程的内存地址空间 那是不是可以理解为 vfork函数所创建的子进程其实是一个子线程?
T:
vfork有些特性是类似线程, 但你不能说它就是线程了吧, 毕竟还有很多地方不一样的。比如必须等待子进程结束才运行父进程。
3.
S:
关于vfork的那段代码运行结果和视频老师讲的不一样
系统返回如下: count = 1 count = 1 段错误
T:
要理解这个问题,对于初学者有一定的难度:
1. 首先你要知道操作系统在调用的你程序时, 实际上是通过exec函数调用你程序产生相应的进程。
2. 虽然C语言程序员只填写了main函数,但是内核执行你的程序时却不是直接进入main函数,而是通过exec先执行一个通用的C启动例程(做一些初始化工作,通常是汇编代码),然后再由这个例程调用main函数。
3. 也就是说,如果你在main函数中返回, 那么就会返回该启动例程;但是如果你在main函数中调用exit或者_exit,其效果是直接结束进程(也就是不会返回启动例程)。 4. 好了, 如果你理解了上面这个过程, 接下来我们从vfork分配子进程的特点来分析这个问题。 1)vfork的第一个特点:分配的子进程会和 父进程共享数据段和堆栈段。而栈,是使函数能返回到原来调用它位置继续执行的关键(调用函数时会将返回地址入栈)。 2)vfork的第二个特点:分配后父进程一定等到子进程先执行完才会执行,因此,一定是子进程先通过main函数返回C启动例程,然后再接下来的启动例程中结束自己,但是,由于子进程main函数的返回,使栈的结构发生了变化,而这个栈是与父进程共用的,因此父进程这时在利用函数返回,就不知道返回到那里去了(由于这个返回值的任意性, 这里出现了段错误,因为正好从这个被破坏的栈中取得的值是一个不可访问的地址)
问题简述
shmget((key_t)1234,sizeof(struct shared_use_st,0666|IPC_CREAT)) 这里把键值指定为1234,有原因吗,是随意写的数吗?
教师解答
对,这个键值就是随便写的, 不过这样写不是很科学,因为系统可能已经用了这个键值,合理的办法是使用ftok()生成键值。
gcc thread_int.c -o thread_int
加 -lpthread 选项。
当你要使用非标准C库(libc)以外的库时,需要使用-l选项,指定要添加的库。 -l选项会在标准的库目录下搜索,例如-lz,连接时会在这些目录下搜索libz.so或libz.a
问题简述
老师上课时说htons htol用于发送时的字节序转换;ntohs ntohl用于接收时字节序转换server_addr.sin_addr.s_addr=htonl(INADDR_ANY); server_addr.sin_port=htons(portnumber); 请问老师这里的htonl和htons是将ip地址和端口号发送到网络吗? 还有在tcp_server 和 tcp_client里的read和write函数用于接收和发送数据,为什么就没有使用字节序转换命令? 困惑我好久了,希望老师解答,谢谢!
教师解答
htonl仅仅是转换字节序, 没有操作发送接收。 read\write处理的数据一般在底层已经进行了字节序的处理