T9的空间

You will never walk alone!

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  69 随笔 :: 0 文章 :: 28 评论 :: 0 Trackbacks
看了下第一次作业,那个排版和高亮背景有点瞎,这次能好点就不错了.

第二章是关于POSIX以及XSI的一些标准和limitation,就不做作业了,直接到第三章,没有睡午觉,有些困,不要写错...

先贴一些比较好的思路
(1)
在AF_LOCAL(Posix: AF_UNIX)的Socket编程中,对Client端来说需要connect
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
这里需要给serv_addr一个length,这个length是一个真实的地址长度。
当socket为AF_UNIX的Socket时 socket address为sockaddr_un里面存放着地址类型以及socket path,我们需要知道sockaddr_un中真正存放数据的长度。

函数offsetof是不错的选择
这个function的实现看起来可以学习,我先抄一段贴下面

#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER )

宏功能:获得一个结构体变量成员在此结构体中的偏移量。

1. ( (TYPE *)0 ) 将零转型为TYPE类型指针;
2. ((TYPE *)0)->MEMBER 访问结构中的数据成员;

3. &( ( (TYPE *)0 )->MEMBER )取出数据成员的地址,即相对于0的偏移量,要的就这个;
4.(size_t)(&(((TYPE*)0)->MEMBER))结果转换类型,size_t应该最终为unsigned int类型。
此宏的巧妙之处在于将 0 转换成(TYPE*),这样结构体中成员的地址即为在此结构体中的偏移量。

这里主要还是利用了 '->' 这个符号的功能,编译器解析这个符号的时候应该就是通过偏移量取值,所以这里先定义好取值规则(TYPE*)然后利用偏移量取值反向再取地址,再然后因为起始地址是0,取回的地址就变成了真正的偏移量。
还有一个知道member求整体的Ptr的Marco应该也蛮好用,括号比较多,我没头去看具体实现了...

 

#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr – offsetof(type,member) );})

宏功能:从结构体(type)某成员变量(member)指针(ptr)来求出该结构体(type)的首指针。

(2)
有讨论一些东西,没有搞清楚,贴在这里以后有心力了再看,在看Rild,然后pthread在做线程同步的时候需要先lock,也许大家都是这样做,也一直这样做,但是突然就想到之前Java的时候讨论过的东西为什么wait/notify 一定要在一个synchronize block中,当然你可以讲,如果不会有exception抛出,你也还可以讲wait本来就会先释放lock然后把当前的thread放到Object waiting thread pool中然后挂起当前线程,实现就是这样子,但是从设计来讲,原因我没有想的特别清楚,如果不去lock,是不是因为wait/notify本身有很多操作没办法做multi thread...

然后就是关于select的一些辅助的Marco,类似FD_SET,FD_ZERO之类的,简单讲就是一个long数组,每个元素的每个bit代表一个fd,然后做set,clear之类的动作,最大不能超过那个1024

今天先到这里,写个序,明天正文...Orz

(3)
继续讨论东西
有人为了在C++中作出类似Java可以自动释放内存的东西,也就是所谓的智能指针,Android有帮忙实现strong pointer/weak pointer,他的大概意思就是用一个第三者来看住当前new出来的object,采用的方式一般是引用计数,这种方式也许在Design Pattern中有专门的名字。一般利用编译器对这个第三者做自动释放的时候去检查计数器,看是否能释放他看管的object,C++里面编译器会自动去call ~Constructor就例如局部变量。

有一些复杂的Case,就算是交叉引用了,Strong Pointer/Weak Pointer就是为了解决交叉引用的问题,从语义上讲父Object引用子Object,用SP,反过来用WP
只要SP为0,就可以释放Memory

今天大家有讲Java的WeakReference,SoftReference,我就含糊了,我以为这东西和上面一样。
Java的WeakReference,SoftReference跟上面讲的完全不一样,由于没分清楚,混淆了。JVM就会处理引用交叉的问题,JVM处理引用交叉可以使用类似有向图,如果呈环状而且环中的任意点都没办法到GC Roots(VM stack中的Reference/static reference/JNI reference),那么就都GC掉应该也没问题。
所以Java中的所谓的WeakReference/SoftReference跟SP/WP不一样,Java中普通赋值的reference都是强可及的Strong Reference。
WeakReference只是用来关心下那些将要被回收却没有回收的Object,一旦被GC Thread扫到就会被释放。
而SoftReference是JVM对Object的Cache,只要内存足够不会被释放。

贴一个讲Android SP/WP的链接,之前有印象看过。
http://blog.csdn.net/luoshengyang/article/details/6786239


(4)
Keep Thinking...
某人让我写一个处理字符串的函数,30min, 我怎么也不能让他失望的,是吧~无论11点多的时候我头有多晕,我很开心的在那里写,很直白的讲,我自己用的本是个游戏机,没啥好环境。用C写了个,然后跑出来的结果出乎预料,我想可能是长时间指手画脚惯了~仔细想了下一些文件操作

然后仔细看了一下二进制文件和文本文件,这也是纠正之前的一些疑惑。
基本概念是:
我自己感觉文本文件和二进制文件没啥区别,文本文件就是有明确普通解码方式的显示字符的文件,可以理解说文本文件也是一种二进制文件,只不过这个二进制文件的解码方式是固定好的(ASCII/UTF-8之类)

然后就是读写文本文件时在Windows上有一些转换,写的时候会在\n前面自动加上\r,读的时候反过来,Linux则没有区别。

有一件事情是要明确知道的
像printf之类的东西,帮助我们输出的,其实我们往printf里面塞的是 int 值,这是一个二进制的值,但是我们从stdout中看到的则已经变成了字符,一定有人帮忙做了转换.
我原本以为printf会是检查目标文件,如果目标文件为二进制则直接输出原本的值,如果目标为文本文件就输出对应值的字符

这种理解是错的,不同的输入输出函数带来了不同的结果
类似printf这种格式话输出函数,会把输出内容按照字符以默认的编码方式encode放入文件,所以那个文件里面写的值已经是真实值的一种显示方式(字符)了
然后scanf这种函数在读的之后,也会把字符转换为对应的值,一般ASCII就直接 -0x30了

像read/write这种function他们不会做任何转换,直接就把值放进去了,所以你用文本文件打开的时候,按照默认的decode方式来解析他的时候会发现是乱码。

这个东西与文本文件二进制文件没有关系。
不知道是不是我自己很弱,现在才知道这个东西。

作业终于开始:
3.1 这章主要讲文件Unbuffered IO,这里的unbuffered是指userspace没有buffer来缓冲,kernel一定还是有缓冲的,一般userspace的缓冲做在标准C lib中
另外像Android这种架构Java layer会做缓冲(BufferedInputStream/BufferedOutputStream, 默认是8K)
Java layer的缓冲可以减少 JNI 调用次数
C lib缓冲可以减少 system call 的次数

3.2 自己实现dup2
不能用fcntl那就只能用dup了
这里是想要让做题的人知道,kernel对进程文件描述符的分配原则是 "取最小的没有使用的"
所以用dup实现Mydup(fd1, fd2)
1.fd2 < fd1: close fd2; dup(fd1)得到的值就是fd2
2.fd2 = fd1: 直接return fd1
3.fd2 > fd1: 那就只能无限dup了,直到返回值为fd2,然后close掉 fd1 ~ fd2-1
这里需要对文件描述符表,文件表,inode之类的概念熟悉。

3.3
这里主要是要说文件表项的分配,每次open kernel都会分配新的文件表项,dup的作用就是拿到另外一个文件描述符指向相同的文件表项,但是每支文件只有同一份
inode。
fd1,fd2会指向同一份文件表项
fd1,fd2,fd3的文件表项会指向同一份inode
fcntl 作用于fd1,F_SETFD用来设定 close_on_exec 标志这个东西是在文件描述符中的,所以只会影响fd1
如果是F_SETFL则会影响fd1, fd2文件状态标志都放在文件表中。

3.4
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
if (fd > 2) close(fd);
这个东西的作用应该就是重定向标准输入输出和错误输出到fd.

3.5
没什么重要的,shell命令一定是从左往右解析执行的

3.6
虽然是append方式打开,这个东西是针对写,lseek可以自己选定读取位置。
write函数是否是会每次先lseek到文件尾部?然后再写,这样之前lseek的设置就无效了
小东西验证。

后面贴下代码
append会影响每次write,只要是O_APPEND打开,每次write都会添加到文件末尾。

Done

posted on 2013-05-22 22:58 Torres 阅读(131) 评论(0)  编辑 收藏 引用 所属分类: APUE

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理