??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品乱码久久久久久按摩 ,亚洲另类欧美综合久久图片区,久久只有这精品99http://www.shnenglu.com/xieshuo/category/20531.htmlYou will never walk alone!zh-cnSun, 21 Jul 2013 14:34:27 GMTSun, 21 Jul 2013 14:34:27 GMT60LTZ看书之APUE14http://www.shnenglu.com/xieshuo/archive/2013/06/07/200852.html Torres TorresFri, 07 Jun 2013 10:52:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/06/07/200852.htmlhttp://www.shnenglu.com/xieshuo/comments/200852.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/06/07/200852.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200852.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200852.html

q个是Muxd一直用的东?br />相当于一个双向PIPE
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



Torres 2013-06-07 18:52 发表评论
]]>
LTZ看书之APUE13http://www.shnenglu.com/xieshuo/archive/2013/06/07/200842.html Torres TorresFri, 07 Jun 2013 06:40:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/06/07/200842.htmlhttp://www.shnenglu.com/xieshuo/comments/200842.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/06/07/200842.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200842.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200842.htmll端IO
每个l端都有输入输出队列
队列都有长度Q如果输入超q输入队列MAX_INPUT长度Q大多数unixpȝ会回昑֓铃来处理?br />但是对于输出队列来讲Q虽然输出队列也有长度,但是一旦写不进ȝ时候,写进E会suspend?br />直至有空闲空?/p>

l端行规E?terminal line discipline
会帮忙做规范处理

l端讑֤属?->termios

struct termios {
 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];
};

local flag影响驱动E序和用户之间的接口
Android上tcflag_t->
typedef unsigned int tcflag_t;

cc_t
typedef unsigned char cc_t;

control flag中很多选项标志都是用几位标识然后用或来做选择

isatty的实玎ͼ借助tcgetattr的出错机Ӟ成功q回0Q否则返?1Q带上ENOTTY

int
isatty (int  fd)
{
  struct termios term;

  return tcgetattr (fd, &term) == 0;
}

AnywayQ终端IO很复?..



Torres 2013-06-07 14:40 发表评论
]]>
LTZ看书之APUE12http://www.shnenglu.com/xieshuo/archive/2013/06/06/200830.html Torres TorresThu, 06 Jun 2013 09:22:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/06/06/200830.htmlhttp://www.shnenglu.com/xieshuo/comments/200830.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/06/06/200830.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200830.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200830.htmlIPC

首先讲到的是PIPEQ这个ƈ不陌生,怺通信的Process必须h关系Q一般是同父亲的
然后讲到了协同进E?br />基本是说有一个进E专门用来接收输入,然后处理Q然后返回结?br />q个可以用PIPE来实?/p>

创徏两个PIPEQ一个用于输入给协同q程Q另外一个用于接收协同进E的输出
fork之后在子q程中将标准输入输出都dup到管道上

而协同进E的写法可以比较commonQ只用关心标准输入输出?br />PIPE在写的时候如果有多个写进E,那么写的数据于 PIPE_BUF 则不会ؕ序,否则自己应该需要做同步了?/p>

然后是FIFOQ这个就是用mkfifo创徏一个fileQ大安ȝ?br />PIPE和FIFO都是半双工的

XSI IPC ->即之前System V IPC
消息队列 信号?׃n存储?/p>

在无兌E之间共享存储段Q一个是使用上面VpȝshmQ另外一个是使用mmap同一文gmapC们自qq程I间?br />
另外是|络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 />



Torres 2013-06-06 17:22 发表评论
]]>
LTZ看书之APUE11http://www.shnenglu.com/xieshuo/archive/2013/06/05/200818.html Torres TorresWed, 05 Jun 2013 08:59:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/06/05/200818.htmlhttp://www.shnenglu.com/xieshuo/comments/200818.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/06/05/200818.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200818.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200818.html13章在讲Daemon ProcessQ没什么特别好写的?br />14 ->高IO

低速系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>

Torres 2013-06-05 16:59 发表评论
]]>
LTZ看书之APUE10http://www.shnenglu.com/xieshuo/archive/2013/06/04/200788.html Torres TorresTue, 04 Jun 2013 07:41:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/06/04/200788.htmlhttp://www.shnenglu.com/xieshuo/comments/200788.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/06/04/200788.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200788.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200788.htmlU程控制

APUE讲的destroy会freeI间Q这件事情看h不太对,也许是Base on实现
L我看到的实现是没有做qg事情的?/p>

 

int pthread_attr_init(pthread_attr_t * attr)
{
    
*attr = gDefaultPthreadAttr;
    
return 0;
}


int pthread_attr_destroy(pthread_attr_t * attr)
{
    memset(attr, 
0x42sizeof(pthread_attr_t));
    
return 0;
}


Attribution有下面这些?br />

 

typedef struct
{
    uint32_t flags;
    
void * stack_base;
    size_t stack_size;
    size_t guard_size;
    int32_t sched_policy;
    int32_t sched_priority;
}
 pthread_attr_t;

我们可以用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    |
 
* +---------------------------+
 
* |                           |
 
* |          TLS area         |
 
* |                           |
 
* +---------------------------+
 
* |                           |
 
* .                           .
 
* .         stack area        .
 
* .                           .
 
* |                           |
 
* +---------------------------+
 
* |         guard page        |
 
* +---------------------------+

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

int  pthread_once( pthread_once_t*  once_control,  void (*init_routine)(void) )
{
    
static pthread_mutex_t   once_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
    
volatile pthread_once_t* ocptr = once_control;

    pthread_once_t tmp 
= *ocptr;
    ANDROID_MEMBAR_FULL();
    
if (tmp == PTHREAD_ONCE_INIT) {
        pthread_mutex_lock( 
&once_lock );
        
if (*ocptr == PTHREAD_ONCE_INIT) {
            (
*init_routine)();
            ANDROID_MEMBAR_FULL();
            
*ocptr = ~PTHREAD_ONCE_INIT;
        }

        pthread_mutex_unlock( 
&once_lock );
    }

    
return 0;
}

所以这个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>

Torres 2013-06-04 15:41 发表评论
]]>
LTZ看书之APUE9http://www.shnenglu.com/xieshuo/archive/2013/06/03/200775.html Torres TorresMon, 03 Jun 2013 09:03:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/06/03/200775.htmlhttp://www.shnenglu.com/xieshuo/comments/200775.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/06/03/200775.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200775.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200775.htmlU程函数
int pthread_equal(pthread_t tid1, pthread_t tid2)
pthread_t pthread_self(void)

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>

typedef struct
{
    
int volatile value;
}
 pthread_mutex_t;

多注意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>

int pthread_mutex_trylock(pthread_mutex_t *mutex)
{
    
int mtype, tid, oldv, shared;

    
if (__unlikely(mutex == NULL))
        
return EINVAL;

    mtype  
= (mutex->value & MUTEX_TYPE_MASK);
    shared 
= (mutex->value & MUTEX_SHARED_MASK);

    
/* Handle common case first */
    
if ( __likely(mtype == MUTEX_TYPE_NORMAL) )
    
{
        
if (__atomic_cmpxchg(shared|0, shared|1&mutex->value) == 0{
            ANDROID_MEMBAR_FULL();
            
return 0;
        }


        
return EBUSY;
    }




__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);
    }



Torres 2013-06-03 17:03 发表评论
]]>
LTZ做作业之APUE8http://www.shnenglu.com/xieshuo/archive/2013/06/02/200761.html Torres TorresSun, 02 Jun 2013 13:52:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/06/02/200761.htmlhttp://www.shnenglu.com/xieshuo/comments/200761.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/06/02/200761.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200761.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200761.html信号
提供异步旉处理方式
触发时机:
1.l端命o
2.g异常Q由kernel抛向对应的Process
3.kill函数/kill命o(用户or Process的user相同Q这里的user id一般是指实际用户ID or 有效用户IDQ如果支?_POSIX_SAVED_IDS,那么查saved-user-id)
4.软g触发(满信号条g)

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>

 

static __sighandler_t
_signal(
int  signum, __sighandler_t  handler, int  flags)
{
    
struct sigaction  sa;
    __sighandler_t    result 
= SIG_ERR;

    sigemptyset( 
&sa.sa_mask );

    sa.sa_handler 
= handler;
    sa.sa_flags   
= flags;

    
if ( !sigaction( signum, &sa, &sa ) )
        result 
= (__sighandler_t) sa.sa_handler;

    
return result;
}



__sighandler_t bsd_signal(
int signum, __sighandler_t handler)
{
  
return _signal(signum, handler, SA_RESTART);
}


__sighandler_t sysv_signal(
int signum, __sighandler_t handler)
{
  
return _signal(signum, handler, SA_RESETHAND);
}



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.



Torres 2013-06-02 21:52 发表评论
]]>
LTZ做作业之APUE7http://www.shnenglu.com/xieshuo/archive/2013/05/31/200728.html Torres TorresFri, 31 May 2013 11:50:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/05/31/200728.htmlhttp://www.shnenglu.com/xieshuo/comments/200728.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/05/31/200728.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200728.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200728.htmlW九?q程关系
也是首先记录基本概念

关于linuxl端的概念,q个最好仔l想一下,因ؓ之后会有伪终端的内容Q如果不想的具体一些,那么会比较难有感觉。下面有个链接,我觉得写的还可以?/span>
http://blog.csdn.net/smstong/article/details/8760331

我写下我的理解,肯定有不太对的地方,但只能到此?/span>

q义的讲: l端是用来和User交互的设备,键盘Q显C器Q打印机...
q里一般讲的是狭义的终?
一般有两种: 字符哑终? 囑Şl端
字符哑终端,是自己没有处理能力Q只能输入输出的;
囑Şl端其实他有处理能力Q例如framebuffer...
linux中,真正能称得上是终端的其实物理lg是键盘+昄器,或者称q两个东西叫做控制台
但是linux虚拟出来?个终端设?/span>
tty1 ~ tty6
?dev/tty0是一个symbol link指向当前l端Q?dev/console则可以ؓ/dev/tty0提供~冲Q这个我不确定)

tty7是图形终?/span>
囑Şl端中,会用软gcMrxvt虚拟出更多的伪终端,cM我们看到?dev/pts/0...

伪终端是一U虚拟终?/span>
但是有时候所谓的虚拟l端q是能对应上物理讑֤

对于伪终端pts和ptm
我自己感觉就像PIPEQ只不过输入输出时有l端行规E来控制格式?/span>

后面有讲会话Q会话由q程l构成,不过我想不清楚运用场?..

q一章有一些没看懂Q进E组Q会话,控制l端...因ؓ不怎么用,先放q里Q以后再R?/span>
没有作业...


Torres 2013-05-31 19:50 发表评论
]]>
LTZ做作业之APUE6http://www.shnenglu.com/xieshuo/archive/2013/05/31/200687.html Torres TorresThu, 30 May 2013 16:25:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/05/31/200687.htmlhttp://www.shnenglu.com/xieshuo/comments/200687.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/05/31/200687.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200687.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200687.html记录一些基本概?/div>
PID == 0的是Swapperq程(调度q程)Q这个Process的RO应该是pre load的时候都攑ֈ内存里面了,不runM盘上的codeQ属于系l进E?/div>
PID == 1的是initq程。这个是一个以rootq行的用戯E?/div>
forkQ我有看C个词fork hope...我觉得不错,我也希望我能fork出hope...
fork的返回状态是有原因的QAPUE的解释还不错?/div>
fork ?父进E中q回子进E的 PIDQ因为没有Q何API能知?child process idQ而且child可能会有很多。。?/div>
fork ?子进E中q回0Q是因ؓ0是swapperq程Q所以没关系Q也没必要返回父q程IDQ可以通过getppid()得到?/div>
fork后,子进E父q程׃n正文 RO
RW ZI Heap Stack是父q程的副本,副本意味着copy
linux已经有很多用COW?copy-on-write)Q这个东西应该是要借助MMU
因ؓ基本fork后会跟execQ那样子所有的东西又都需要马上被替换?/div>
都设|ؓRead OnlyQ无论是parentq是child只要一个试图修改,那么copyQ单位应该是MMU的Page
linux有提供cloneQ这个东西可以由调用者控制什么东西是要和父进E共享的Q我q没看到pthread的实玎ͼ猜想应该是通过q东西实现资源共享的?/div>
tips:{
对于字符串求长度Qsizeof会计nullQ这也正常,因ؓsizeof()是算memory被分配的大小Qstrlen计算的是有效字符的长度,不包含null?/div>
如果字符串是帔RQsizeof能在~译时被优化Q也变成帔RQstrlen则是函数调用不能被优化?/div>
}
vfork
具体实现我没有具体去惻Iq个东西也没有什么特别的Q跟fork不一L是,他必L上exec or exitQ否则会run在父q程I间而不做Q何复?/div>
所以会有同步,在子q程q未call exec or exit前,父进E会被suspend。要不然父进E受的媄响便是未知的?/div>
另外q里也有讨论exit函数在做清理工作时对的处理
应该是说 一般exit不会d关闭的动作Q而把qg事情留给kernelQ只是flush stream好Q否则类似遇到vforkq种会在父进E空间做事情的,
如果call exit把流l关闭了Q会有一些不预期的结果?/div>
父进E提前终止,那么子进E的父进E都会被|ؓ1--> init process.
init process会ؓ每个子进E无论是自己fork出来的还是因为父q程提前l止而领ȝ做wait获取l止状态,避免zombieq程
处理方式应该是收到SIGCHLD后call wait(null)
waitpd的函数还蛮多?..
对于不想使自q子进E处于zombie状态的Q自己有q想做一些事情的且不惛_心子q程l束状态的可以fork两次QexitW一ơ出来的q程Qwait他,然后W二ơfork出来?/div>
q程的父q程变成init了,不过需要用这U技巧的Case我没惛_。。?br />
关于execpd函数Q我x好还是记住,因ؓl常会用Q不能每ơ用都去查吧?br />一?个,exec能给的最多就q三个参敎ͼ要run的程序\径;要给run的程序的参数Q要lrun的程序的环境变量
其中只有execve?system callQ其他都是库函数?br />execve(const char* name, char* const argv[], char* const envp[])

q里又有讲三个用户ID的用?br />实际用户IDQ有效用户IDQ保存的讄用户ID

q里有讲一个CaseQ应该算l典CaseQ也只有cMCase才能让你明白保存的设|用户ID的用?br />
manE序|用户ID/讄lIDQ就会在两种权限中切换?br />q行man的时?
real user id == login id
effective user id == man
saved effective user id == man

在man讉K完他自己拥有的那些file后,惌行一些命令call setuid(getuid())因ؓ我们不是root
real user id == login id
effective user id == login id
saved effective user id == man
q个时候运行命令就是我们login时候的user的权?br />
完了后面惌|回ȝ时候再call setuid(euid),q里euid是manQ之前可以保存在man自己的Context?br />q个时候euid == saved effective user idQ所以effective user id又被讄为manQ这U情况下如果没有saved effective user id那用h限就回不M?br />real user id == login id
effective user id == man
saved effective user id == man

所以注意setuid 如果是root用户Q那么三个ID都会被设|成目标IDQ如果不?br />则effective user id可能会改?当目标ID?real user id or saved effective user id的时候,从设计的角度仔细惻Iq样子也合理?br />
system的实?br />execel shellQ而不是直接去fork/execel本n要system的程序,那样会变得异常复杂,你需要解析cmdStringQ分dE序和参敎ͼ带入和shell一L环境变量Q找到目的程序,execute他,然后带回l果?br />一般会去call system的程序不要用set-user-idQ这样容易导致安全泄霌Ӏ容易让system出来的那个process权限扩大Q不易控制?br />
贴一个system的实玎ͼ非常nice
#include <sys/types.h>
#include 
<signal.h>
#include 
<stdlib.h>
#include 
<unistd.h>
#include 
<paths.h>
#include 
<sys/wait.h>

extern char **environ;

int
system(
const char *command)
{
  pid_t pid;
    sig_t intsave, quitsave;
    sigset_t mask, omask;
    
int pstat;
    
char *argp[] = {"sh""-c", NULL, NULL};

    
if (!command)        /* just checking */
        
return(1);

    argp[
2= (char *)command;

    sigemptyset(
&mask);
    sigaddset(
&mask, SIGCHLD);
    sigprocmask(SIG_BLOCK, 
&mask, &omask);
    
switch (pid = vfork()) {
    
case -1:            /* error */
        sigprocmask(SIG_SETMASK, 
&omask, NULL);
        
return(-1);
    
case 0:                /* child */
        sigprocmask(SIG_SETMASK, 
&omask, NULL);
        execve(_PATH_BSHELL, argp, environ);
    _exit(
127);
  }


    intsave 
= (sig_t)  bsd_signal(SIGINT, SIG_IGN);
    quitsave 
= (sig_t) bsd_signal(SIGQUIT, SIG_IGN);
    pid 
= waitpid(pid, (int *)&pstat, 0);
    sigprocmask(SIG_SETMASK, 
&omask, NULL);
    (
void)bsd_signal(SIGINT, intsave);
    (
void)bsd_signal(SIGQUIT, quitsave);
    
return (pid == -1 ? -1 : pstat);
}

q里使用了vfork和execveQ他的实现细节以及可UL性做的还是蛮完美的?br />
作业Q?br />8.1 如果q如此那么exit没有关闭stdoutQ这在之前也讲过一般的C库都不会q么多此一举,一般他们只会去flush stream不会close
所以如果想辑ֈ那种效果Q可以自己去昄去fclose

8.2
q个有点复杂啦,vfork后理Z应该立即调用exec才对Q如果不去exec or exitQ那么子q程run在父q程的数据空_如果子进E从另外一个函数返回,不call exitQ那么就会一直等到main函数退出,父进E才会执行,但是q个时候stack里面已经没有M东西了,我不定会发生什么事?br />
8.5
不提供返回保存的有效用户ID的函?br />
8.6 8.7E后贴上source code.




Torres 2013-05-31 00:25 发表评论
]]>LTZ做作业之APUE5http://www.shnenglu.com/xieshuo/archive/2013/05/28/200655.html Torres TorresTue, 28 May 2013 12:00:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/05/28/200655.htmlhttp://www.shnenglu.com/xieshuo/comments/200655.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/05/28/200655.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200655.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200655.html
所谓的启动例程用C写v来一般是q样Q但一般情况这个会是汇~来?br />exit(main(argc, argv))

exit函数
_exit和_Exit立即q入kernelQexit则需要做完必要的清理工作Q先run注册q的l止处理E序Q然后清理没有关闭的?br />exit _Exit是ISO C标准Q_exit则是PosixQ所以头文g不一?br />前面是stdlib.h 后面是unistd.h

关于mallocQcallocQrealloc
malloc分配的空间初始g定Qcalloc会帮忙清Ӟrealloc可以动态分配合适的大小I间Q如果不够会有copy原始数据的动作,所以对realloc之前的memory记录指针不是好方法,因ؓrealloc完就可能失效?br />
q三个都是去call sbrk来扩大羃heap
但一般只是扩大,在free的时?malloc 会把扩大?memory cacheh(virual memory)

setjmp, longjmp
跌{函数Q支持跨函数的蟩转,goto是函数内跌{
注意: longjmp到setjmp的点后,一般情?全局/局?局部静态变量都没办法恢复到setjmp时的|register/volatile变量在编译后(cc -O)会放到寄存器中,q些都能实现回滚。这也就说明setjmp的时候,jmp_bufq没有保存这些倹{?br />
7.1 如果不调用return ?exit 函数q回值用了printf的返回|Orz...我没x楚怎么做的?br />
7.2 取决于printf面对的设备类型,行缓冲的话,到换行׃被输出,如果是全~冲Q那么则要么需要call fflushQ要么等stream被close?br />
7.3 不用参数传递,不用全局变量QOrz...要传递argc, argv -->NO

7.4 通常null是0Q一般指针ؓ null 的时候意味着I指针引用,一?都不会去放数据,RO的v始位|在一个更高的地址Q?会是无效的,用来指引E序出错?br />
7.5
typedef void func(void);
int atexit(func* fp);
或?br />typedef void (*func)(void);
int atexit(func fp);
我喜Ƣ下面那U,因ؓ函数本n是个pointer?br />
7.6 calloc会将分配的空间清ӞISO C不保?值和I指针相{?br />
7.7 size输出的是静态的ROQRWQZIQ像HeapQStack是runtime才有的?br />
7.8 理论上不带debug信息?out文g应该大小都是{于RO+RW+ZI的?br />
7.9 q就?a?so的区别了Qlink的时候静态库会被直接copyq来Q所以会变大很多?br />
7.10 变量作用域的故事?img src ="http://www.shnenglu.com/xieshuo/aggbug/200655.html" width = "1" height = "1" />

Torres 2013-05-28 20:00 发表评论
]]>
LTZ做作业之APUE4http://www.shnenglu.com/xieshuo/archive/2013/05/28/200624.html Torres TorresTue, 28 May 2013 11:24:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/05/28/200624.htmlhttp://www.shnenglu.com/xieshuo/comments/200624.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/05/28/200624.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200624.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200624.html阅读全文

Torres 2013-05-28 19:24 发表评论
]]>
LTZ做作业之APUE3http://www.shnenglu.com/xieshuo/archive/2013/05/27/200611.html Torres TorresMon, 27 May 2013 08:42:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/05/27/200611.htmlhttp://www.shnenglu.com/xieshuo/comments/200611.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/05/27/200611.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200611.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200611.htmlq里要稍微写一些linux下复杂的权限理Q应该只是一部分知识,q有一些关于cap的东西以后再看?/p>

与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好多细?..

 


 



Torres 2013-05-27 16:42 发表评论
]]>
LTZ做作业之APUE2http://www.shnenglu.com/xieshuo/archive/2013/05/22/200521.html Torres TorresWed, 22 May 2013 14:58:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/05/22/200521.htmlhttp://www.shnenglu.com/xieshuo/comments/200521.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/05/22/200521.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200521.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200521.html
W二章是关于POSIX以及XSI的一些标准和limitationQ就不做作业了,直接到第三章Q没有睡午觉Q有些困Q不要写?..

先脓一些比较好的思\
(1)
在AF_LOCAL(Posix: AF_UNIX)的Socket~程中,对Client端来说需要connect
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
q里需要给serv_addr一个lengthQ这个length是一个真实的地址长度?br />当socket为AF_UNIX的Socket?socket address为sockaddr_un里面存放着地址cd以及socket pathQ我们需要知道sockaddr_un中真正存放数据的长度?br />
函数offsetof是不错的选择
q个function的实现看h可以学习Q我先抄一D脓下面

#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



Torres 2013-05-22 22:58 发表评论
]]>
LTZ做作业之APUE1http://www.shnenglu.com/xieshuo/archive/2013/05/21/200470.html Torres TorresTue, 21 May 2013 15:25:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/05/21/200470.htmlhttp://www.shnenglu.com/xieshuo/comments/200470.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/05/21/200470.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200470.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200470.html

记性不好,所以作业做h--从第一章开始,期望有始有终
1.1 Ҏ目录Q?Q来_没有parentQ所?.' or '..'没有区别了Q可以用ls -li来看inodeQ?.. 代表他本w?/span>
1.2 多实例,Process ID递增Q分配Process ID的具体方?->//TODO:L情景分析
1.3 const char* 攑ֈperror中不惌perror自己改,其实我觉得strerror也可以const int
1.4 errno related
比较早之前errno是by process的,qƈ不合适,Linux支持多线E存取errno
extern int* __errno_location(void)
#define errno (* __errno_location())
MacroZ个函敎ͼ使得__errno_location有机会返回一个TSL的variable
q里APUE有Wrap一些简单的打error log的函敎ͼ׃errno是一个by thread variableQ所以必d保存
要不然后面print之类的system call同样有可能出现error然后覆盖掉errno
有看到变参函敎ͼU正了我自己长期的一个误区,之前一直以为变参函数只能用在特定的Case下才有用Q例如scanf/printf之类的输入输出函?/span>
因ؓ他们都有带类似format的参敎ͼ能够通过%dQ?c之类的东西找到后面的变参的个C及类型,今天有去看一下va_list/va_arg/va_end的实玎ͼ会发现变参函数是Q本来也应该是一U更加common的设?/span>
q里带提一下function call的大体流E,q里需要比较多的背景知识,cM函数调用U定Q程序内存分?..
找来一张图比较好看Linux process userspace的布局Q印象中windows也一样只不过windows默认?G/2GQlinux是大安知道?G/3G


userspace?~0xC0000000Qkernel space(0xC0000000~0xffffffff)的样子跟q个差别比较大,那边分vmalloc/kmallocq有cMhigh memory的概念,q里主要贴出userspaceQ可以看一下ROQRWQZIQHeap的位|,Z提一下整个linux virtual memory其实都可以分Z部分: anonymous memory/mapped memoryQ像RO是mapped memoryQRW开始是mapped memoryQ只要有人改变初始|那就会变成anonymous memoryQZIQHeapQStackq些都是anonymous memoryQ与函数调用相关的主要是stack -->stack的地址是向低地址增长的,栈底在高地址Q栈在低地址
然后介绍两种常用的函数调用约定,一U是C语言默认的函数调用约?__cdecl; 另外一U是PASCAL默认的调用约?__stdcall
q两U都是从叛_左将参数压栈Q然后再push ebp; mov ebp, esp; 再然后压入函数局部变量,不一L是cdecl是由caller function函数参数出栈,stdcall是由callee function函数出栈?/div>
q两U方式各有好处,慨括讲一下cdecl的话每个调用者都必须dpop stack的动作,code size会变大;stdcall则在callee function本n来看会比较单U?/div>
但是q种cd比较难从~译器的角度来支持变参函数?/div>
变参函数都是cdecl
可以玩一下这L函数...

 

 1#include <cstdlib>
 2#include <iostream>
 3
 4using namespace std;
 5
 6void foo(int cnt, )
 7{
 8    cout << "start foo" << endl; 
 9    int* p = &cnt;
10    for(int i = 0; i < cnt; i++){        
11        cout << *(++p) << endl;
12    }

13    cout << "end foo" << endl;
14}

15
16int main(int argc, char *argv[])
17{
18    int a = 1, b = 3, c = 5, d = 7;
19    void (*functest)(int cnt, );
20    functest = foo;
21    functest(4, a, b, c, d);
22    system("PAUSE");
23    return EXIT_SUCCESS;
24}


加一点对va_list/va_arg/va_end的说法,其实他的实现蛮灵zȝ

///stdarg.h
#define va_start _crt_va_start
#define va_arg _crt_va_arg
#define va_end _crt_va_end  

///vadefs.h
#define _ADDRESSOF(v)   ( &reinterpret_cast<const char &>(v) )
typedef 
char *  va_list;
#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap)      ( ap = (va_list)0 )

贴一D늽上看到的应该是i386的实玎ͼcMq种变参函数会直接去用指针操作stack来找参数的,因ؓ涉及到对其的问题一定是by platform的,不太好移?/span>
像_INTSIZEOF(n) 是int对其
大概讲下意?va_list 是 char*Q是一个用来找参数ptr的游?/span>
va_start(ap, v)  通过W一个固定参数v 初始?ap
va_arg(ap, t)  q里qType t了,所以ƈ不一定需要类似printf?format 来找Qcaller和callee可以有一些其他的U定方式Q这个返回当前类型ؓt的参数的|q且ap指向下个参数Q因Z前ap被初始化的时候其实他q不知道他指向的参数的类型?/span>
va_end(ap) 清掉ap
多说一句,printfpd的函数还蛮多的,fprintf/sprintf/vprintf/svnprintf...带f的是面向FILE streaming的,s是针对char buffer的,v则是说参数是带va_list的,n则是具体指size
1.5/1.6讨论32位表C时间溢出的Q不惛_{案Q时间比较晚Q第一章作业写完?/span>

 

记录一些关于系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寄存器作ؓ最??

 



Torres 2013-05-21 23:25 发表评论
]]>APUE杂记http://www.shnenglu.com/xieshuo/archive/2013/05/19/200399.html Torres TorresSun, 19 May 2013 07:17:00 GMThttp://www.shnenglu.com/xieshuo/archive/2013/05/19/200399.htmlhttp://www.shnenglu.com/xieshuo/comments/200399.htmlhttp://www.shnenglu.com/xieshuo/archive/2013/05/19/200399.html#Feedback0http://www.shnenglu.com/xieshuo/comments/commentRss/200399.htmlhttp://www.shnenglu.com/xieshuo/services/trackbacks/200399.htmlq里会记录一些比较杂qD落Q作为APUE作业的开始,以后会增添,或许q会整理Q比较确定的是会贴一些章节作业上来,我目前不知道隑ֺQ初始想法是单看看书Q如果可以会ȝL景分析,因ؓ我n边也正好q有一本。我惌头子正式开工了...监督自己Q期望能完成有收莗?/p>

Torres 2013-05-19 15:17 发表评论
]]>
Ʒþþþ㽶| þۺۺϾþúݺݺ97ɫ88| ղƷþþþþþ| ҹƷþþþþ| 91龫Ʒ91þþþ| þþƷaĻ| ҹѸþӰԺ| þþþþžžƷӰԺ| þþһ| ξþ99Ʒþþþþ| Ʒһþ㽶߿ۿ | רþۺϾĻ| һ㽶þֻ| 99þùۺϾƷŮͬͼƬ| 91Ʒ91þþþþ| ޵һƷƷþ| þ| պþӰԺ| þþžžƷ99Ʒ| ɫþˬˬƬAV| ޾Ʒһþ| 99þ뾫Ʒϵ| þþþþŮ| þù㽶һƷ| ƷҹþøƬ| þþƷ99þ޶| þþþ߽ۺϳ| ձvaҹĻþ| þùһƬѹۿ| þþƷһ| ĻƷѾþþ| ŷþþþƷ| 99reþþƷҳ2020| 97þù¶Ʒ| þþþav| Ӱ7777þþƷˬ| ŷպƷþ | ޾Ʒھþ| ƷŮٸavѾþ| Ʒ99Ʒþ| þ99Ʒþþþ|