??xml version="1.0" encoding="utf-8" standalone="yes"?> q个是Muxd一直用的东?br />相当于一个双向PIPE l端行规E?terminal line discipline l端讑֤属?->termios struct termios { local flag影响驱动E序和用户之间的接口 cc_t control flag中很多选项标志都是用几位标识然后用或来做选择 isatty的实玎ͼ借助tcgetattr的出错机Ӟ成功q回0Q否则返?1Q带上ENOTTY int return tcgetattr (fd, &term) == 0; AnywayQ终端IO很复?.. 创徏两个PIPEQ一个用于输入给协同q程Q另外一个用于接收协同进E的输出 而协同进E的写法可以比较commonQ只用关心标准输入输出?br />PIPE在写的时候如果有多个写进E,那么写的数据于 PIPE_BUF 则不会ؕ序,否则自己应该需要做同步了?/p>
然后是FIFOQ这个就是用mkfifo创徏一个fileQ大安ȝ?br />PIPE和FIFO都是半双工的 XSI IPC ->即之前System V IPC 在无兌E之间共享存储段Q一个是使用上面VpȝshmQ另外一个是使用mmap同一文gmapC们自qq程I间?br />
Process A open ptm得到fdmQ然后fork出process BQprocess B open pts得到fdsQ然后将0,1,2都dup到fds?br />那么fds变成了process B的控制终?br />后面再process B中做标准IO操作的时候就会像PIPE直接影响到fdm
l端行规E在pts之上
没什么特别要记录的,在网上search了下Q脓个链接,里面会介l一些基本概?
http://www.cnblogs.com/Anker/archive/2012/12/25/2832568.html
]]>
每个l端都有输入输出队列
队列都有长度Q如果输入超q输入队列MAX_INPUT长度Q大多数unixpȝ会回昑֓铃来处理?br />但是对于输出队列来讲Q虽然输出队列也有长度,但是一旦写不进ȝ时候,写进E会suspend?br />直至有空闲空?/p>
会帮忙做规范处理
tcflag_t c_iflag;
tcflag_t c_oflag;
tcflag_t c_cflag;
tcflag_t c_lflag;
cc_t c_line;
cc_t c_cc[NCCS];
};
Android上tcflag_t->
typedef unsigned int tcflag_t;
typedef unsigned char cc_t;
isatty (int fd)
{
struct termios term;
}
]]>
首先讲到的是PIPEQ这个ƈ不陌生,怺通信的Process必须h关系Q一般是同父亲的
然后讲到了协同进E?br />基本是说有一个进E专门用来接收输入,然后处理Q然后返回结?br />q个可以用PIPE来实?/p>
fork之后在子q程中将标准输入输出都dup到管道上
消息队列 信号?׃n存储?/p>
另外是|络IPC?br />是复习下吧Q之前这块儿看的比较?br />int socket(int domain, int type, int protocol)
domain标识address family -> AF_INET, AF_INET6, AF_UNIX(AF_LOCAL), AF_UNSPEC
type标识socketcd -> SOCK_DGRAM(UDP), SOCK_RAW(IP), SOCK_SEQPACKET, SOCK_STREAM(TCP)
一般protocol都设|ؓ0Q一般address family和typep认要用的protocol
SOCK_SEQPACKET和SOCKQSTREAM很像Q前一个提供面向数据报文的服务Q而后面这U则是面Ҏ?br />SOCK_SEQPACKET使用场景SCTPQ脓一个SCTP的简要介l?br />http://www.cnblogs.com/qlee/archive/2011/07/13/2105717.html
涉及|络必要清楚字节序的问题Q字节序与字W编码是两g不同的事情,都要x楚的Q但是要提一下UTF-8q是一U专门设计用来做|络传输的字W编?br />无需兛_字节序的问题Q所以传输的上层数据可以用UTF-8Q就不用担心local host和remote host的主机字节序不一栯导致ؕ序了?br />
但是很多协议头必dW合TCP/IP协议的字节序规范QTCP/IP是big endian
关于Big endian和Litter endian我比较容易忘记具体的样子Q但是他的出发点是低地址Q低地址装的是最高有效字节那么就是big endianQ否则就是litter endian?br />
关于socket有几个可能比较模p的地方
connectӞ也就是client端,如果fd没有l定到某个地址Q那么kernel会帮忙将其绑定到默认地址; 所以bindqg事情是Client和Server都需要做的事情,调用listen之前也一?br />然后accept的时候,如果你关心对方的地址Q那么提供addr(_)和lenQ返回的时候就能知道?br />另外UDP(SOCK_DGRAM)也可以Call connectQ之后就可以直接call send/writeQ而不必每ơ都call sendto指定对端地址?br />
sendto中flag一般给0Q如果是紧急数据给MSG_OOB
文g描述W的传输Q目的是惌不同的process在不同的文g描述W中׃n文g表?br />所以做法上pȝ会这P传输文g表指针然后放到接收端的第一个可用的文g描述W上?br />q个我在linux上没扑ֈ实现Q因个功能还是有蛮多替代Ҏ的?br />
]]>
低速系l调用,也就是有信号发生会返?errno ?EINTR?/p>
盘文gIO虽然有gӞ但是q个不能是低速系l调?/p>
APUE介绍的低速系l调?br />PIPEQ终端设备,|络讑֤ d
L数据/写无I间(例如TCP卡Congestion window)
打开某些Ҏ文g
加记录锁的文件读?br />ioctlQIPC
文g锁又叫做 byte-range lockingQ针对特定的文g区域Q适合数据库文?br />Posix标准
int fcntl(int fd, int cmd, .../* struct flock* flockptr */)
cmd -> F_GETLK,F_SETLK,F_SETLKW
F_SETLKW是F_SETLK的Blocking版本 W means wait
重要数据l构是struct flock ->
struct flock {
short l_type;
short l_whence;
off_t l_start;
off_t l_len;
pid_t l_pid;
__ARCH_FLOCK_PAD
};
锁定整个file的方? l_whence = SEEK_SET, l_start = 0, l_len = 0
l_type的两clock
F_RDLCKQF_WRLCKq两U锁的特性很像rw lock
不过与读写锁不一L是或者这栯
Posix.1没有规定下面q种情况: process A在某文g区间上设|了一把读锁;process B试在这个文件区间加上写锁的时候suspendQprocess C再尝试获取读锁,如果允许
process C拿到读锁Q那么process B会可能永远拿不到写锁,zL饿死
pthread里面的rw lock的实C在这U情况下suspend掉process C的读锁请求;但是目前文g区域锁的实现我不太确?/p>
q里看文件区域锁q是比较Ҏ带来deadlock?br />例如process A锁住F1的某个区域,然后去锁F2的一个区域,q时候F2的这个区域被process B锁住Q那么process A׃suspendQ如果这个时候process Bq来要锁F1的这个区?br />׃发生deadlock
关于文g区域锁的l承和释?br />1.fork后,文g区域锁ƈ不承,l承了就完了Q不同的process有可能同时q同一件事情,把数据搞?br />2.close(fd)?fd对应的文仉p释放了,文g锁挂在inode上,close的时候kernel会去扫描对应的inode上与q个PID相关的lockQ释放掉Q而ƈ不去兛_是哪个文件描q符?/p>
者是哪个文g表,q很重要Q因为lockf中ƈ不记录fdQ他们只是弱兌关系Q这个很重要?br />3.exec后,文g锁会l承原来执行E序的锁(fork之后拿到的lock)Q如果fd带有close-on-exec那么ҎW二条,q个fd对应的file上的锁都会被释放?/p>
后面讲了STREAMSQ感觉linux上用到的不多Q需要在~译kernel时动态加?/p>
IO多\转接Q主要是Z实现polling既所谓的轮询
主要函数有selectQpselectQpollQepoll
select也会是低速系l调用,那么有可能被信h?br />pselect有参数可以设定信号屏蔽集Q也提供更高_ֺ的timer
poll的方式与select有不太一L地方Q但是功能相同,epoll更适合大数据量?/p>
readv和writev
C下面两条够?br />一个称为scatter read(散步?Q另外一个称为gather write(聚集?
q两个函C面对一个buffer链表?br />
readn和writen
q个比较像现在Android里面socket的read和write方式Q保证能read/write n byte数据Q在内部做@?br />我比较好奇这两个是否会处理signalQ想来应该是会处理的Q遇到EINTR帮忙重启好?/p>
我没有找到Bionic库的实现
存储映射IO
q个很重要,mmap用的很多Q映到processI间的位|在 stack以下Qheap以上的部分,map完后q回低地址?/p>
#include<sys/mman.h>
void* mmap(void* addr, size_t len, int prot, int flag, int filedes, off_t off)
prot -> PROT_READ,PROT_WRITE,PROT_EXEC,PROT_NONE
prot指定的对映射存储区的保护不能过文g的open权限
?flag?MAP_FIXED的时候OS会保证分配的memory起始地址为addrQ否则只是给OS一个徏议?br />一般徏议addrl?Q让OS来决定?/p>
MAP_SHARED是说Ҏ区域的存储(write)会导致修改该文g?br />MAP_PRIVATE则是Ҏ区域的操作会常见一个映文件的副本?br />
后面有个例子用了lseek
使用lseek增加文g长度的方式,先lseek一个|如果q个值大于文件本w的长度Q那么下一ơ写׃加长该文Ӟq且在文?br />中Ş成一个空z,未写q的内容全部Mؓ0?br />mmap只能map文g的最大长度,过的地Ҏ办法同步到文件?/p>
APUE讲的destroy会freeI间Q这件事情看h不太对,也许是Base on实现
L我看到的实现是没有做qg事情的?/p>
Attribution有下面这些?br />
我们可以用malloc和mmaplThread分配stackQ指定stack大小和位|?低地址)
mutex属?br />两个东西
1.q程׃n属性,PTHREAD_PROCESS_PRIVATE or SHARED
意思是说如果这个Mutex是分配在两个q程׃n的memoryQ然后设|ؓshared mutex可以用于进E同?br />2.cd属性,normal;errorcheck;recurive
意思是定义Mutex本n的特性,q里更正下前面那章提到的错误
只有normal的mutex才会在再ơ加锁时发生deadlock
errorcheck的会直接q回错误
recurive本n允许,会有计数
rw lock和condition属?br />只支持第一?br />
TLS变量
先看下TLS的位|?/p>
pthread_internal_t是记录线E自己本w的一些属性的变量Qguard page是U程attr上设|的防止栈溢出的扩展内存
创徏TLS变量的方?br />1.创徏KeyQ这个Key是这个Process中所有Thread可以׃n讉K的,然后每个Thread自己d联自qThread Local变量
int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void*))
创徏key的时候需要保证唯一调用Q也是不会有两个Thread同时调用Q然后发生一些base on实现的不定的结果,可以使用pthread_once
pthread_once的实现很单,用mutex做互斥量保证pthread_once_t的访问,然后利用pthread_once_t做flag来调用init_routine
所以这个pthread_once_t必须是全局or静态变?br />pthread_once最常用的case除了拿到TLS key外,init函数l常会用这个,避免多线E同时调用?br />
然后是thread cancel
Android Bionic库没有实?pthread_setcancelstate(int state, int* oldstate)以及pthread_cancel()
q里thread的取消,有些是取消不掉的Q例如一些blocking callQ所有的取消均是需要设定一些取消点的,
有h有专门针对Android没有Thread Cancel来想办法
基本是thread signalQ在signal handler中去call pthread_exit();
or用PIPE在多路复用中break出来
http://blog.csdn.net/langresser/article/details/8531112
如果信号与硬件故障or计时器超时相养I那么信号会发送到引v事g的该U程中去Q其他信号会发送到L一个线E?br />q里是说的POSIXU程模型Q一般的信号都会发送给q程中没有阻塞该信号的某个线E。APUE讲的某个没有d该信LU程Q其实有Ҏp?br />
但是Linux的实C一Plinux的thread是clone出来的,是׃n资源的独立进E,q样子其实蛮自然的,也不Ҏ复杂?br />linux中,有可能线E就不会注意到该信号Q这栯也有Ҏp,Ml端驱动E序的信号会信号通知到进E组Q这样子所有的thread׃都收C?br />如果你不x有的U程都去兛_信号Q那么可以用一个专门处理信LU程
先将其他U程的signal都pthread_sigmask SIG_BLOCK掉,然后使用sigwait在特定的U程来等
pthread_sigmask和sigprocmask很像
thread与fork
fork后的子进E会l承mutex, rw lock, condition的状?br />但是子进E中只会存在一个线E,也就是那个调用fork的线E的副本Q有个复杂的事情是关于上面承下来的那些东西Q子q程׃只有一个线E,没办法知?br />上面那三个东西的具体状态,需要有个清理锁的动?-->pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
我目前不知道q个东西的用场景,而且不容易控制?br />因ؓ一般如果我们fork后都会接execuQ这样地址I间׃改变Q那么这些承的东西没用了?br />
然后有谈一点关于线EIO的东?br />pwrite/pread
也就是原子的q行lseek和r/wQ但是这个ƈ不能保证大家常见的冲H问题,也就是一个thread在写另外一个要读,所以这两个东西q不能解军_步的问题?br />
作业:
12.3 理论上函数开始时屏蔽所有信P函数l束时恢复,是可以做到异步信号安全的。如果你只是屏蔽一些信P那么没办法做刎ͼ因ؓ如果有其他信可来,你call的函数里面有一些不可重入的函数Q同样不能保证是异步安全的?br />
12.5 fork可以在拿来执行可执行E序Q现在应该就q一个Case?/p>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr
void* (*start_rtn)(void), void* restrict arg)
thread被创建的时候会l承调用U程的Q点环境和信号屏蔽字,但是该线E的未决信号集将会被清楚Q?br />清除未决信号集这件事情应该是没有疑问的,在thread创徏之前pending住的信号Q不应该deliverl下一?br />Ps: U程的Q点环境指的是? 看来以后我应该去注意下QҎ的运原理?/p>
pthread相关的函C直接q回错误码,而不会和一些system call一P|全局errnoQ两U方式都有好处,一个可以讲q回?br />带回的错误代码集中v来,范围~小Q另外一个非常方便,关键点在于这一cd用errno的是否真的异常是可以q的?/p>
pthread_createq回之前有可能新的线E就已经开始run?/p>
启动函数 void* (*start_rtn)(void)
可以通过returnl回来,也可以通过pthread_exitl?br />q个会存在一个地?br />通过pthread_join(tid, void**)取回?/p>
q里join的和java join是一L功能
如果q个东西是一个很大的东西:)Q那么放到heap是最好的选择Q不要放到stack上了Q不然线E返回这东西没了,join取到的内存地址变成一个无效的了,SIGSEGV׃被发出来
pthread_cancelQ同一个进E可以callQ提求终止线E?/p>
pthread_cleanup_push
pthread_cleanup_pop
U程分离Q这样子U程l止后可以释放一些资源,而不用一定要其他人来join
Ҏ有两U,新徏的时候加上分d?br /> pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
或者call pthread_detach(pthread_t tid)
U程互斥与同?/p>
多注意volatile变量Q这个东西理Z是让编译器不要做优化,不要cache volatilecd的变量,
每次都去内存地址中拿Q而不是寄存器/高速缓存副本,q种变量极容易被~译器不知道的h改变Q例如其他线E?/p>
静态初始化:
#define PTHREAD_MUTEX_INITIALIZER {0}
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER {0x4000}
#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER {0x8000}
所谓的动态初始化
pthread_mutex_init; pthread_mutex_destroy
然后是一些pthread mutex的基本处理函C
lock,unlock
trylock;
q个trylock需要好好理解下Q尝试获取lockQ如果OKQ那么lock他然?return 0; 否则也不会suspend住,而是直接q回EBUSY
pthread_mutex_destroy, 会先去try lockQ然后处理掉q个mutex的倹{?/p>
q里E微提一?/p>
__likely/__unlikely函数用来告诉~译器优化代码,cMif else中最有可能or最没有可能发生的Case
mutex有deadlock的问题,单线E,如果有代码重入重复获取锁׃deadlockQ因ZCCunlock的地方去Q另?br />常见的deadlock是lock比较多,又没有设计好序Q这个应该从业务逻辑上就应该定义好,当然有时候有的h用的时候or改代码的时?br />q没有理清这些lock的关p,是否有dependencyQ比较难通过借用一些编译系l来Cover住,然后改完有bug?br />
然后q有一U需要设计好的是锁的_度
太粗太细都不?br />_度太粗Qlock住的东西太多Q很多线E都要等lockQ最后这个东西会演变成一个串行的东西
_度太细Qlock又变的太多,不停的需要lock/unlockQperformance׃变差?br />目前看到的Android上的很多lock都太_?br />
rw?->d?br />基本理念是M会媄响界区发生变化
所以读模式的rw lock可以多个人占用,写模式的rw lock时能被一个线Elock
只要有写模式lockhQ那么后面的L式lockh一般实现是都会被Suspend住,不然因ؓL式下Q可以重复lockQ如果不
suspendQ那么写模式的lockh有可能永q得不到相应?br />rw锁一般用?read?write行ؓ多的多的场景Q允许多U程q发去读Q单一U程d?br />
然后会想到spinlockQ可以去|上search看下基本概念Qspinlock一般在SMP架构下会比较有效果?br />
mutex是一U同步机制or讲这是一U互斥机?-> Java synchronize
q一U就是条件变?condition.. -> wait/notify
q里有段话很?br />条g变量l多个线E提供了一个回合的场所Q条件变量与互斥量一起用的时候,允许U程以无竞争方式{待特定的条件发生?br />
作业:
1.U程之间传递数据不要用stack变量Q用攑ֈ下面q些地方的变量就好,RW/RO/ZI/Heap没事了
4.
现在一般都是这?/p>
pthread_mutex_lock(&s_startupMutex);
s_started = 1;
pthread_cond_broadcast(&s_startupCond);
pthread_mutex_unlock(&s_startupMutex);
会在broadcast后才unlock
否则有比较高的概率,unlock后,被其他线E将条gҎQ这个时候broadcast出去没有意义了?br />但是q种也有可能会被另外一个线E,qwait在那里的U程改变条g?br />
所?pthread_cond_wait q回q不意味着条g一定ؓ真了
最好是always check条g
cMq种
while (s_started == 0) {
pthread_cond_wait(&s_startupCond, &s_startupMutex);
}
q里也稍微解释下Killq个东西Qkill函数Qkill命oq不是字面上杀掉某些东西,kill只是在特定的旉发送信P
具体的处理取决于信号本n和信L处理方式?/p>
信号的处理方?
q个有点cMJava Exception的处理方式,catch住or往上throw
APUE讲的信号处理方式有三U?br />1.忽略QSIGKILL/SIGSTOP不能忽略Q一般如果Process自己不管的话Q应该会走到pȝ默认的处理流E中Q所以不能忽略这件事情是pȝ自己׃保证的?br />2.捕捉信号Q例如SIGCHLD,一般parent会call waitpid取子q程l止状态,避免他处理Zombie状态?br />3.执行pȝ默认动作
我感??可以归ؓ一cdQ只是有些signal没有pȝ默认动作Q然后就跌M。一般的pȝ默认动作也就是终止进E?/p>
SIGKILL/SIGSTOP不能被忽略的原因我觉得讲的不错,提供用户l止q程的可靠方法,不然后箋有可能进E的行ؓ是未定义?
signal函数定义:(
void (*signal(int signo, void(*func)(int)))(int);
q个C函数的声明有炚w看懂
APUE讲signal的语义与实现有关Q所以徏议大安用sigaction
不过我看了下Android Bionic下的实现Q分别包含BSD以及SYSV的版本,但也都变成了sigactionQ所以一般在C库中׃证了q一点,也就无所谓了?/p>
exec函数会讲信号处理方式q原为系l默认,q个应该毫无疑问Qexec后地址I间׃一样了Q保留之前的捕捉函数也是无意义的Q在q之前是有意义的Q我的意思是说fork后exec之前?/p>
后面有列一大堆是否可以重入的函敎ͼ不太惌Q然后讲Cmalloc
我想不能重入的函数无外乎两种cd
one: 自己有maintain一些全局or static变量 --> malloc l护分配内存时static heap linklist
two: 函数参数里面有引用之cȝQ会影响调用者的情况?/p>
然后我看到这个立马就惛_了线E安全,malloc是线E安全的?
ȝ了下Bionic的实玎ͼ然后又看到下面q个名字 Dong LeaQ马上就会想到Java Concurrent库,看到q个你直接就会有xQBionic里面q个malloc肯定是线E安全的Q?br />有时候被q些东西搞的很篏Q比较烦他,而且Bionic里面用的malloc的那个实现版?aka dlmalloc)我又没看?(Q只好去|上search了一下,有个人做q实验,有些l论q是可以参考的
http://www.360doc.com/content/12/0420/23/168576_205320609.shtml
ȝ来说Q这个东西取决于C库实玎ͼ我想Bionic和Glibc都应该一样会支持两种不同的版本,然后~译的时候就可以定是否有线E相x作,然后在link的时候linkq来不同的版?/p>
U程安全和信号安全是两个概念
如果在线E安全的malloc中,信号处理函数中发生重入,那么应该是会发生dead lock
如果是非U程安全中,那么应该是所谓的 undefined behavior.
前面q有一个概率忘记写
早期的UnixpȝQ如果系l在执行一个低速系l调?基本可以ȝ为blocking IO:包括IPCQFile IOQioctl)Q那么如果捕捉到信号Q那么系l就会中断这个system call -->EINTR, q在当时是有理由的,而且理由看v来也合理Q但是由于user有时候ƈ不知道某些系l调用是否是低速系l调用,BSD引进了自动重启的功能Qlinux followq种规则
然后有几个版本的signal函数
signal默认自动重启
_signal(signum, handler, SA_RESTART) q是׃在sigaction中的flag为SA_RESTARTQ上面sysV的实现我不想多写了?br />sigaction也就是可选的了?/p>
但一般我印象中好?read/write都是会自己判断返回g及errno 是否?EINTRQ然后retryQ因Z面这U方式依赖系l实玎ͼ需要将所有的signal都设定ؓSA_RESTARTQ那么如果有某个信号发生的时候,被他INTR的系l调用才会自动重启,不知道默认signal在注册处理行为的时候是不是如此Q感觉不太好用?/p>
alarm函数
对于很多像alarmq种函数Q在设计时or使用时均应该考虑临界值的问题
alarm的唯一性,是by process的,process单例
所以如果alarm两次Q那么第一ơ会被覆盖,怎么处理W一ơ未完成的情?>q回g带回来剩余的旉
怎么取消讑֮的alarm
传入gؓ0 means cancel
M了,q个东西设计的时候还蛮完善的
后面q有一堆有关signal的标准函敎ͼq里也就不一一列D
作业:
1.Lfor(;;), 那捕捉到SIGUSR1p回了Qpause()只要捕捉CP{信号处理完时自己就会返回ƈ带回EINTR。不晓得为啥有这U题?..
2.实现sig2strQ这有点无聊?:(不写
3.画runtime stack的样子?br />4.IO操作的超时最好不要采用alarm的方式,各种原子问题Qselect/poll是最好的选择?br />后面有好一些是要写代码?..
我略惻I然后׃太愿意写?
PS:有些东西略难...我也是有Ҏ不清楚的样子Q打慢慢搞?br />
后面军_把标题改一下,利看完书吧...Orz.
与process兌的ID
谁executeq个process的hUCؓreal user idQ应该就是登陆时使用的user
real group id也一?
一般在一个登陆Session中,q两个值都不会改变Q但是超U用戯E可以改?br />像Android中每个APK有独自的User idQ然后类似rild之类的native deamon process׃试改变自己的user id为类似radio之类的东ѝ?/p>
在运行中查权限所使用的idUCؓ有效用户idQeffective user id
然后q有有效lID
附加lID
一般有效用户ID == 真实用户IDQ?有效lID == 真实lID
但是如果在可执行文g的st_mode中有讄 set-user-ID/set-group-ID
那在执行q个文g的时?有效用户ID和有效组ID会变成文件的owner
一般有讄set-user-ID/set-group-ID的程序都会获得额外的权限
关于文g权限Q有一些容易引赯解的Q也q有一些我自己也没有理解清楚的
文g权限比较好理解,O_TRUNC需要文件具有写权限?br />
文g夹的写权限,应该是cM能不能在其中create/update/delete文g和文件夹
文g夹的L限,应该是L件夹里面的文?文g夹列表,通常我们 ls 当前文g夹就必须hL?br />文g夹的执行权限Q这个东西听说又叫搜索位Q通常我们cd XXXQ就必须在当前文件夹下搜索XXX是否存在Q然后就是当我们讉KcMq种很长路径的文?aaa/bbb/ccc/dd.txt
对aaaQbbbQccc必须h执行权限Q就是搜?/p>
一般如果具有读权限应该就可以搜烦Q如果这之前有区别,是应该是搜索的范围大于能读到的内容?br />也就是之后需要知道一个Folder本n里面有写什么内容,我目前知道的是一定有当前的文件列?-> TODO: 看情景分?or ȝ?ls 的实玎ͼls里面有比较多参数有些是需要x的有些是需要r的,例如 ls -l如果没有执行权限只能拿?name ,能知道是folderq是fileQ除此之外其他的东西都拿不到Q文件本w的权限QuserQgroup
-->linux目录中记录的应该是只有两个东?inode & name.q与文gpȝ的实现有兟?/span>
另外增删文g都需要WX权限
另外内核Ҏ件操作权限的判断序...如果是owner׃看owner权限Qgroup权限׃会看了,如果在group中则others也就不看了,q个逻辑上正常,而且可以想一下kernel的实玎ͼ一定是if-else的判断出l果后直接返回?/p>
q里p提如果新建文?文g夹的时候文件夹的owner user id和group id是谁
user id会是process 有效用户ID
group id可以有两U选择父folder的group idQor process有效lID
linux中根据文件系l的不同有的可以在mount fs的时候选择
文g长度: st_size
lseek到文件末之后的I间Q会照成文gI洞
文g长度?I洞的大,但是q些I洞未必会占用磁盘空间?/span>
du 命o可以看磁盘空间大?/span>
W号链接和所谓的链接完全是两回事,l读4.14Q不要去上网searchcM我这U自p录给自己看的blog...:(
q章内容比较多而且杂,主要是stat中的每个参数的意义,需要思考想清楚的东西也比较多,有比较多关于文g操作的System Call
作业开?
之后只写有点意义的题目,无意义的也没什么可以写的pass
4.1 stat和lstat的区别,stat基本不会兛_是否是S_IFLNK(W号链接)Q应该是看到S_IFLNK会往下去扄正的FileQ然后拿到属性?/span>
而lstat旁道S_IFLNK则会直接q回。第一ơ看到这L函数设计怪怪的Q我的初始感觉是反的。我觉得stat是一个common的设计,不会针对不同的Filecd来做一些区别。Orz...最后不是?/span>
4.2 umask 777意味着rwxrwxrwx全部变没掉,但是q也没关p,不知道出题h的意?/span>
4.5 目录和符号链接的长度不可能ؓ0Q目录创建出来就会包? ?..而且 . 的inode指向自己本n会占盘I间Q符号链接肯定也是不能ؓ0的,其中有存指向的链接path
4.6 q个有点意思,后面贴代?/span>
4.7 q个看了下答案,没看?gt;Z么kernel默认的创建文件赋予的权限“可能会,也可能不?#8221;受unmask的值的影响?
4.8 du df的区?..
4.9 ~ 后面的题大概看了下,不想写了Q好多细?..
]]>
#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER )
宏功能:获得一个结构体变量成员在此l构体中的偏U量?/strong>
1. ( (TYPE *)0 ) 零转型为TYPEcd指针;
2. ((TYPE *)0)->MEMBER 讉Kl构中的数据成员;
3. &( ( (TYPE *)0 )->MEMBER )取出数据成员的地址Q即相对?的偏U量Q要的就q个;
4.(size_t)(&(((TYPE*)0)->MEMBER))l果转换cdQsize_t应该最lؓunsigned intcd?
此宏的y妙之处在于将 0 转换?TYPE*)Q这L构体中成员的地址即ؓ在此l构体中的偏U量?br />
q里主要q是利用?'->' q个W号的功能,~译器解析这个符L时候应该就是通过偏移量取|所以这里先定义好取D?TYPE*)然后利用偏移量取值反向再取地址Q再然后因ؓ起始地址?Q取回的地址变成了真正的偏U量?br />q有一个知道member求整体的Ptr的Marco应该也蛮好用Q括h较多Q我没头ȝ具体实现?..
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr – offsetof(type,member) );})
宏功能:从结构体Q?strong>typeQ某成员变量Q?strong>memberQ指针(ptrQ来求出该结构体Q?strong>typeQ的首指针?br />
(2)
有讨Z些东西,没有搞清楚,贴在q里以后有心力了再看Q在看RildQ然后pthread在做U程同步的时候需要先lockQ也许大安是这样做Q也一直这样做Q但是突然就惛_之前Java的时候讨的东西ؓ什么wait/notify 一定要在一个synchronize block中,当然你可以讲Q如果不会有exception抛出Q你也还可以讲wait本来׃先释放lock然后把当前的thread攑ֈObject waiting thread pool中然后挂起当前线E,实现是q样子,但是从设计来Ԍ原因我没有想的特别清楚,如果不去lockQ是不是因ؓwait/notify本n有很多操作没办法做multi thread...
然后是关于select的一些辅助的MarcoQ类似FD_SETQFD_ZERO之类的,单讲是一个long数组Q每个元素的每个bit代表一个fdQ然后做setQclear之类的动作,最大不能超q那?024
今天先到q里Q写个序Q明天正?..Orz
(3)
l箋讨论东西
有hZ在C++中作出类似Java可以自动释放内存的东西,也就是所谓的指针QAndroid有帮忙实现strong pointer/weak pointerQ他的大概意思就是用一个第三者来看住当前new出来的objectQ采用的方式一般是引用计数Q这U方式也许在Design Pattern中有专门的名字。一般利用编译器对这个第三者做自动释放的时候去查计数器Q看是否能释放他看管的objectQC++里面~译器会自动去call ~Constructor׃如局部变量?br />
有一些复杂的CaseQ就是交叉引用了,Strong Pointer/Weak Pointer是Z解决交叉引用的问题,从语义上讲父Object引用子ObjectQ用SPQ反q来用WP
只要SP?Q就可以释放Memory
今天大家有讲Java的WeakReferenceQSoftReferenceQ我含p了Q我以ؓq东西和上面一栗?br />Java的WeakReferenceQSoftReference跟上面讲的完全不一P׃没分清楚Q淆了。JVM׃处理引用交叉的问题,JVM处理引用交叉可以使用cM有向图,如果呈环状而且环中的Q意点都没办法到GC Roots(VM stack中的Reference/static reference/JNI reference)Q那么就都GC掉应该也没问题?br />所以Java中的所谓的WeakReference/SoftReference跟SP/WP不一PJava中普通赋值的reference都是强可及的Strong Reference?br />WeakReference只是用来兛_下那些将要被回收却没有回收的ObjectQ一旦被GC Thread扫到׃被释放?br />而SoftReference是JVM对Object的CacheQ只要内存够不会被释放?br />
贴一个讲Android SP/WP的链接,之前有印象看q?br />http://blog.csdn.net/luoshengyang/article/details/6786239
(4)
Keep Thinking...
某h让我写一个处理字W串的函敎ͼ30minQ?nbsp;我怎么也不能让他失望的Q是吧~无论11点多的时候我头有多晕Q我很开心的在那里写Q很直白的讲Q我自己用的本是个游戏机Q没啥好环境。用C写了个,然后跑出来的l果Z预料Q我惛_能是长时间指手画脚惯了~仔细想了下一些文件操?br />
然后仔细看了一下二q制文g和文本文Ӟq也是纠正之前的一些疑惑?br />基本概念?
我自己感觉文本文件和二进制文件没啥区别,文本文g是有明普通解码方式的昄字符的文Ӟ可以理解说文本文件也是一U二q制文gQ只不过q个二进制文件的解码方式是固定好?ASCII/UTF-8之类)
然后是d文本文g时在Windows上有一些{换,写的时候会在\n前面自动加上\rQ读的时候反q来QLinux则没有区别?br />
有一件事情是要明知道的
像printf之类的东西,帮助我们输出的,其实我们往printf里面塞的?int |q是一个二q制的|但是我们从stdout中看到的则已l变成了字符Q一定有人帮忙做了{?
我原本以为printf会是查目标文Ӟ如果目标文gZq制则直接输出原本的|如果目标为文本文件就输出对应值的字符
q种理解是错的,不同的输入输出函数带来了不同的结?br />cMprintfq种格式话输出函敎ͼ会把输出内容按照字符以默认的~码方式encode攑օ文gQ所以那个文仉面写的值已l是真实值的一U显C方?字符)?br />然后scanfq种函数在读的之后,也会把字W{换ؓ对应的|一般ASCIIq?-0x30?br />
像read/writeq种function他们不会做Q何{换,直接把值放q去了,所以你用文本文件打开的时候,按照默认的decode方式来解析他的时候会发现是ؕ码?br />
q个东西与文本文件二q制文g没有关系?br />不知道是不是我自己很弱,现在才知道这个东ѝ?br />
作业l于开?
3.1 q章主要讲文件Unbuffered IOQ这里的unbuffered是指userspace没有buffer来缓Ԍkernel一定还是有~冲的,一般userspace的缓冲做在标准C lib?br />另外像Androidq种架构Java layer会做~冲(BufferedInputStream/BufferedOutputStream, 默认?K)
Java layer的缓冲可以减?JNI 调用ơ数
C lib~冲可以减少 system call 的次?br />
3.2 自己实现dup2
不能用fcntl那就只能用dup?br />q里是想要让做题的h知道Qkernel对进E文件描q符的分配原则是 "取最的没有使用?
所以用dup实现Mydup(fd1, fd2)
1.fd2 < fd1: close fd2; dup(fd1)得到的值就是fd2
2.fd2 = fd1: 直接return fd1
3.fd2 > fd1: 那就只能无限dup了,直到q回gؓfd2Q然后close?fd1 ~ fd2-1
q里需要对文g描述W表Q文件表Qinode之类的概늆悉?br />
3.3
q里主要是要说文件表的分配Q每ơopen kernel都会分配新的文g表项Qdup的作用就是拿到另外一个文件描q符指向相同的文件表,但是每支文g只有同一?br />inode?br />fd1Qfd2会指向同一份文件表?br />fd1Qfd2Qfd3的文件表会指向同一份inode
fcntl 作用于fd1QF_SETFD用来讑֮ close_on_exec 标志q个东西是在文g描述W中的,所以只会媄响fd1
如果是F_SETFL则会影响fd1, fd2文g状态标志都攑֜文g表中?br />
3.4
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
if (fd > 2) close(fd);
q个东西的作用应该就是重定向标准输入输出和错误输出到fd.
3.5
没什么重要的Qshell命o一定是从左往双析执行的
3.6
虽然是append方式打开Q这个东西是针对写,lseek可以自己选定d位置?br />write函数是否是会每次先lseek到文件尾?然后再写Q这样之前lseek的设|就无效?br />东襉K证?/p>
后面贴下代码
append会媄响每ơwriteQ只要是O_APPEND打开Q每ơwrite都会d到文件末?br />
Done
加一点对va_list/va_arg/va_end的说法,其实他的实现蛮灵zȝ
记录一些关于系lȝ与CPU“位数"的基本概?/p>
通常所说的CPU的位敎ͼ32位or64位CPUQ指的是ALU(术逻辑单元)的宽度,也就是这个ALU处理数据的基本单元的宽度
所以数据ȝ基本会和ALU宽度相同(有例外,q个我没x楚工作原? -->应该是可以新加一些Module来做转换?br />而地址ȝ则是CPUd的能力,一个是怎么d址Q一个是d地址后,地址中内容的宽度(当然q个宽度跟地址cd(byteQshortQint)有关Q但送给CPU的时候一般是单位ơ数送数据ȝ的宽度的数据)Q地址ȝ军_CPU能访问的Memory的范围?/p>
8086?6位ALU 20位数据ȝd1M
每次CPU送出的地址都是16位,然后加上D寄存器作ؓ最??