一:Process(进程)
是程序执行的过程,包括执行,等待,就绪.process并行运行在虚拟空间,包括code,data,stack部分,
分为user mode和kernel mode.
启动:前台启动,后台启动,调度启动.
调度命令:ps -ef; Nice; kill; crontab(至后台).
创建进程:
pid_t fork(void) sys/type.h,unistd.h
result=0: child process
1: error
Oth:father process
pid_t vfork(void)
copy-on-write
执行进程:
int execl(const char *path, const char *arg, ...) list unistd.h
int execv(const char *path, char *const argv[]) vertor
int execle(const char *path, const char *arg, ..., char *const envp[])
int execve(const char *path, char *const argv[], char *const envp[])
int execlp(const char *file, const char *arg, ...)
int execle(const char *file, const char *arg, ..., char *const envp[])
char *arg[] = {"env", "NULL"};
char *envp[] = {"PATH=/tmp", "USER=sunq", NULL};
if(execve("/bin/env", arg, ,envp) < 0)
{ perror("execve error:"); }
退出进程:
void exit(int status) exit(0);退出并保存buffer stdlib.h
void _exit(int status) 直接退出 unistd.h
父进程阻塞并等待:直到子进程结束或接到signal
pid_t wait(int *status) sys/type.h,sys/wait.h
*status =NULL:不管状态
!=NULL:指定status结束的子进程
pid_t:结束的子进程的进程号.
pid_t waitpid(pid_t pid, int *status, int options)
pid=0,<-1:同组的.
-1:任何的子进程.
>0:指定的.
option=WNOHANG: 父进程不阻塞,直接返回.
WUNTRACED: 阻塞到指定status出现
0: 阻塞
守护进程:
五步: fork()
openlog("this process name", LOG_PID, LOG_DAEMON) 创建一个连接到系统日志,/var/log/messages
setsid()<0 创建新的会话组,并任组长.
syslog(LOG_ERR, "%s/n", "setsid err") 写入信息, syslog.h
chdir("/") 工作目录改为根目录
unmask(0) 文件权限为0
for(i=0;i<MAXFILE;i++)
close(i); 关闭控制终端文件.
二:threads(线程)
多线程共用一个进程的文件描述,信号处理和用户地址空间。却创建了多个线程控制表和堆栈寄存器。
分用户级线程(一个阻塞会引起多个阻塞)和核心级线程(可以调度)。1对1,1对多(多处理器).
2.6.13使用NPTL(Native POSIX Thread Library),仍是1:1模型.
创建线程:
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void*), void *arg) pthread.h
通过设置属性CLONE_VM,CLONE_FS,CLONE_FILES(共享文件描述符表)CLONE_SIGHAND(共享信号句柄表)和CLONE_PID(共享进程ID)来调用__clone(),
__clone设置栈并调用do_fork()这个系统调用.
exit线程:
void pthread_exit(void *retval)
父线程同步等待退出:
int pthread_join(pthread_t th, void **thread_return)
abort线程:
int pthread_cancel(pthread_t thread)
相当于abort向目标线程发Cancel信号,而pthread_join()、pthread_testcancel()、pthread_cond_wait()、pthread_cond_timedwait()、 sem_wait()、sigwait()以及read()、write()等会引起阻塞的系统调用都是Cancelation-point.
int pthread_setcancelstate(int state, int *oldstate) 收到cancel信号后设为CANCLED状态或忽略cancel信号继续运行
int pthread_setcanceltype(int type, int *oldtype) 立即cancel或延迟到Cancelation-point
int pthread_testcancel(void) 检查是否处于Canceld状态,是则进行取消动作,否则直接返回
线程属性:
int pthread_attr_init(pthread_attr_t *attr)
int pthread_attr_setscope(pthread_attr_t *attr, int scope) 绑定时间片,和内核线程一起调度
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)脱离和主线程同步,当退出时立即释放资源
int pthread_attr_setschedparam(pthread_attr_t *attr, struct sched_param *param)优先级设定
schedpolicy 调度策略,SCHED_OTHER(默认值), SCHED_RR,SCHED_FIFO
inheritsched 使用新的还是继承调度策略
用来处理exit,cancel退出的cleanup:(atexit)
void pthread_cleanup_push(void(*routine), (viod*), void *arg)
void pthread_cleanup_pop(int execute) 非0:弹出程序并执行,0:不执行
成队出现,设定非正常exit,cencel时释放资源的函数,在pop时执行。
pthread_cleanup_push(pthread_mutex_unlock, (void*)&mut);
pthread_mutex_lock(&mut);
.../* do some work */
pthread_mutex_unlock(&mut);
pthread_cleanup_pop(0)
互斥mutex:
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr_t *mutexattr)
mutexattr :PTHREAD_MUTEX_INITIALIZER 加锁后阻塞另一个要加锁的线程.
:PTHREAD_RECURSIVE_MUTEX_INITIALIZER 加锁后阻塞另一个要加锁的线程,并计数.
:PTHREAD_ERRORCHECK_MUTEX_INITIALIZER 加锁后不阻塞另一个要加锁的线程而返回EDEADLK错误代码.
int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
int pthread_mutex_destroy(pthread_mutex_t *mutex)
条件变量:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
线程在锁定了一个互斥后,经常需要某个条件到来,则用pthread_cond_wait阻塞并检查指定的条件,没有满足就解锁指定的互斥,进入睡眠,直到条件满 足后重新锁定该互斥,并唤醒被挂起的线程。
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
int pthread_cond_destroy(pthread_cond_t *cond)
int pthread_cond_signal(pthread_cond_t *cond)
int pthread_cond_broadcast(pthread_cond_t *cond)
三,IPC:(同步异步,通讯)
unix pipe:在进程间以半双工方式通信,存在于内存.
unistd.h
int pipe(int fd[2])
创建无名管道,在进程组里通信,使用2个文件描述符,一个读fd[0],一个写fd[1],一般通过fork来继承创建的管道,close(pipe_fd[0])等可以关闭
一个方向的通道.read(fd[0],buf,100),write(fd[1],buf,5)进行读写.
FILE *popen(const char *command, const char *type)
创建标准流管道, fd=popen("ps -ef","r/w"),文件指针连接到comamnd的输入/输出.相当于创建管道->fork->在父子进程关闭不需要的文件描述符-> exec->执行命令这个过程
int pclose(FILE *stream) 关闭标准流管道
int mkfifo(const char *fielname, mode_t mode)
有名管道,在2个进程间通信,建立后可以象文件一样操作. if( mkfifo("/tmp/myfifo", O_CREAT|O_EXEC|)<0 )
unix signal:异步通讯,可以在用户和内核中进行,是对中断机制的一种模拟.
signal.h,sys/types.h
int kill(pid_t pid, int sig) 发送signal到指定的用户组的所有进程.
int raise(int sig) 发送一个signal给自己.
unsignted int alarm(unsigned int second) 定时发送一个signal给自己.
int pause(void) pause自己直到捕捉到signal
void (*signal(int signum, void(*handler)(int)))(int) 用指定函数替代原signal本进程指定的操作
整体是一个带int的函数指针,带2个参数,signum和*handle函数指针
int sigempty(sigset_t *set)
int sigfillset(sigset_t *set)
int sigaddset(sigset_t *set,int signum)
int sigdelset(sigset_t *set,int signum)
int sigismember(sigset_t *set,int signum) 初始化一个信号集
int sigprocmask(int how,const sigset_t *set,sigset_t *oset) 改变当前进程的信号集
how=SIG_BLOCK,SIG_UNBLOCK,SIG_SETMASK; sigprocmask(SIG_BLOCK,&set,NULL)
int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact) 设定新的sigaction
struct sigaction{
void (*sa_handler)(int signo); 信号关联函数,SIG_DFL;SIG_IGN..
sigset_t ds_mask; 信号集
int sa_flags; SA_NODEFER|SA_NOCLDSTOP|SA_RESTART|SA_ONESHOT
void (*sa_restore)(void);
}
int sigpending(sigset_t *set) 当允许运行时,用sigpending判断是否有阻塞了的signal.
Example: sigset_t set;
sigemptyset(&set); sigaddset(&set,SIGQUIT); sigprocmask(SIG_BLOCK,&set,NULL); sigemptyset(&action1.sa_mask);
action1.sa_handler=myfunc; sigaction(SIGINT,&action1,NULL)
posix shm
#ifdef _POSIX_MAPPED_FILES
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
prot:访问权限,PROT_READ,PROT_WRITE,PROT_EXEC,PROT_NONE(不可访问)
flags:MAP_SHARED,MAP_PRIVATE,MAP_FIXED
fd:映射的文件符
int munmap(void *start, size_t length)
posix sem
semaphore.h
int seminit(sem_t *sem, int pshared, uint value) pshared=0
int sem_wait(sem_t *sem) P操作,信号量的值减1,小于0时将阻塞.
int sem_trywait(sem_t *sem)
int sem_post(sem_t *sem) V操作
int sem_getvalue(sem_t *sem)
itn destory(sem_t *sem)
systemV shm:从内核的预留内存空间,映射一部分到进程的私有地址空间.实现多个进程间数据共享,当然要考虑同步机制.
sys/type.h,sys/ipc.h/,sys/shm.h
int shmget(key_t key, int size, int shmflg) 申请内存.IPC_PRIVATE,shmflg:权限值
int *shmat(int shmid,const void *shmaddr,int shmflg) 映射内核内存和用户空间
int shmdt(const void *shmaddr) 撤消映射
systemV sem:信号量,根据PV原理实现大型数据的同步.
sys/type.h,sys/ipc.h,sys/sem.h
struct sembuf{ushort sem_num; 要操作的信号在信号集里的编号
short sem_op; 信号的值+sem_op, 可以用来做PV操作,为正,占用资源.为负,阻塞并释放资源.0,阻塞到信号量为0
short sem_flg; IPC_NOWAIT(并返回出错),IPC_UNDO(退出进程时恢复信号量的值)
}
int semget(key_t key, int sems, int semflg) 申请和获得semid,包含sems个信号集
int semop(int semid, struct sembuf *sops, unsigned nsops) 操作信号量
nsops:信号集中信号的数量.
调用成功都返回0。失败返回-1,errno被设为以下的某个值:
E2BIG:一次对信号的操作数超出系统的限制
EACCES:调用进程没有权能执行请求的操作,并且不具有CAP_IPC_OWNER权能
EAGAIN:信号操作暂时不能满足,需要重试
EFAULT:sops或timeout指针指向的空间不可访问
EFBIG:sem_num指定的值无效
EIDRM:信号集已被移除
EINTR:系统调用阻塞时,被信号中断
EINVAL:参数无效
ENOMEM:内存不足
ERANGE:信号所允许的值越界
int semctl(int semid, int semnum, int cmd, union semun arg) 控制信号量的设定
cmd: IPC_STAT读取一个信号量集的数据结构semid_ds,并将其存储在semun中的buf参数中。
IPC_SET设置信号量集的数据结构semid_ds中的元素ipc_perm,其值取自semun中的buf参数。
IPC_RMID将信号量集从内存中删除。
GETALL用于读取信号量集中的所有信号量的值。
GETNCNT返回正在等待资源的进程数目。
GETPID返回最后一个执行semop操作的进程的PID。
GETVAL返回信号量集中的一个单个的信号量的值。
GETZCNT返回这在等待完全空闲的资源的进程数目。
SETALL设置信号量集中的所有的信号量的值。
SETVAL设置信号量集中的一个单独的信号量的值。
systemV mq:消息队列存在于内核空间,由内核维护.
sys/type.h,sys/ipc.h,sys/shm.h
struct msqid_ds{ struct ipc_perm *msg_prem;
struct msg *msg_first;
struct msg *msg_last;
...};
int msgget(key_t key, int flag) 申请和获得msgid,flag:IPC_CREAT|0666
int msgsnd(int msqid, const void *msgbuf, size_t size, int flag) 发message到mq.
struct msgbuf{long mtype;char mtex[1]};
flag:IPC_NOWAIT,0:阻塞至发送.
int msgrcv(int msqid, struct msgbuf *msgbuf, int size, long msgtype, int flag)
msgtype:0 接收第一个msg
>0 接收第一个类型为msgtype的消息
<0 接收第一个最小且小于此绝对值的类型
flag: MSG_NOERROR,IPC_NOWAIT,0
int msgctl(int msgid, int cmd, sturct msqid_ds *buf) 控制消息队列
cmd:IPC_STAT 读取msqid_ds的内容,放入buf
IPC_SET 写入msqid_ds的ipc_perm
IPC_RMID 移走消息队列
四,网络编程:
应用层协议Application:HTTP,FTP,TELNET
传输层协议Transport:TCP(为应用程序提供可靠的通讯连接,大量数据传输),UDP(无通讯连接,少量数据或安全性低的(video)传输)
网络层协议Internet:ICMP(发送有关数据包的传送错误的协议),IGMP(向多路广播路由器报告主机组成员的协议),IPv4,IPv6
网络接口层协议link:ARP,RARP(获得同一网络层中的硬件地址),MPLS(多协议标签协议)
TCP协议里的三次握手:client-> syn J ->server
client<- syn k,ack J+1 <-server
client-> ack k+1 ->server
同时TCP实体采用的基本协议还是个滑动窗口协议.
图片1
TCP数据报头:
ACK:带不带确认号,PSH:接收到直接送app,RST:复位,SYN:连接时用,FIN:断开连接
图片2
UDP数据报头:
1,数据结构
netinet/in.h
struct sockaddr{
ushort sa_family; AF_IENT(ipv4),AF_INET6(ipv6),AF_LOCAL(UNIX域协议),AF_LINK(链路地址协议),AF_KEY(密钥socket)
char sa_date[14]; 14字节的协议地址,包括该socket的IP地址和端口号
}
struct sockaddr_in{
short int sa_family; 地址族
unsigned short int sin_port;端口号
struct in_addr sin_addr; IP地址
unsigned char sin_zero[8]; 填0以保持和sockaddr一样大小
}
2,大小端模式下,CPU和Internet间的数据转化:
uint16_t htons(unit16_t host16bit)
uint16_t ntohs(unit16_t net16ibt)
uint32_t htonl(unit32_t host32bit)
unit32_t ntohl(unit32_t net32bit)
3,地址格式的转化:192.168.0.189 <-> socket中的二进制
arpa/inet.h
int inet_pton(int family, const char *strptr, void *addptr)
int inet_ntop(int family, void *addptr, const char *strptr)
4,主机名和IP地址间的转化:
struct hostent{
char *h_name; 主机名
char **h_alisees; 别名
int h_addrtype; 地址类型
int h_length; 地址长度
char **h_addr_list; 指向地址指针数组的指针
}
struct addinfo{
int ai_flags; AI_PASSIVE,AI_CANONNAME
int ai_family; 地址族
int ai_socktype; socket类型
int ai_protocol; 协议类型
size_t ai_addrlen; 地址长度
char *ai_canoname; 主机名
struct sockaddr *ai_addr; socket结构体
struct addrinfo *ai_next; 下一个addinfo
}
netdb.h
struct hostent *gethostbyname(cosnt char *hostname)
string gethostbyaddr(string ip_address)
int getaddrinfo(const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result)
hostname:主机名 service:服务端口号 hints:服务线索 result:返回结果
Example: struct addrinfo hints,*res=NULL;
hints.ai_family=PF_UNSPEC;
hints.ai_socktype=SOCK_DGRAM;
hints.ai_protocol=IPPROTO_UDP;
rc=getaddrinfo("127.168.0.189","123",&hints,&res);
5,socket操作的基本函数
sys/socket.h
int socket( int family, int type, int protocol )
AF_INET; IPv4协议
AF_INET6; IPv6协议
AF_LOCAL; UNIX域协议
AF_ROUTE; 路由套接字
AF_KEY; 密钥套接字
SOCK_STREAM; 字接流套接字
SOCK_DGRAM; 数据报套接字
SOCK_RAW; 原始套接字
int bind( int sockfd, struct sockaddr *my_addr, int addrlen )
int listen( int sockfd, int backlog )
int accept( int sockfd, struct sockaddr *addr, socklen_t *addrlen )
int connect( int sockfd, struct sockaddr *serv_addr, int addrlen )
int send( int sockfd, const void *msg, int len, int flags )
int recv( int sockfd, void *buf, int len, unsigned int flags )
int sendto( int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen )
int recvfrom( int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen )
flags一般为0
6,实例:
TCP使用的模型: USER SERVER
socket->bind socket->bind->listen
connect -> accept
send/sendto -> recv/recvfrom
recv/recvfrom <- send/sendto
close close
五,文件I/O
Stream I/O
sys/stat.h,fcntl.h,unistd.h
int open( const char *pathname, flags, int perms )
flags: O_RDONLY|O_WRONLY|O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_TRUNC|O+APPEND
perms: 0600
int close( int fd )
ssize_t read( int fd, void *buf, size_t count )
ssize_t write( int fd, void *buf, size_t count )
off_t lseek( int fd, off_t offset, int whence )
int fcntl( int fd, int cmd, struct flock *lock )
cmd: F_DUPFD Copy file
F_GETFD Get close-on-execute mark
F_SETFD Set close-on-excute mark
F_GETFL Get open flag
F_SETFL Set open flag
F_GETFK Get lock
F_SETFK Set lock
F_SETLKW Set lock and wait
F_GETOWN Get SIGIO and SIGURG's pid
F_SETOWN Set the file's pid
struct flock{ to sovle file share
short l_type; F_RDLCK,F_WRLCK,F_UNLCK
off_t l_start; Compare position
short l_whence; SEEK_SET,SEEK_CUR,SEEK_END
off_t l_len;
pid_t l_pid;
}
FILE I/O type:
1,Block
2,Non-block
3,I/O switch
4,Signal driver
5,Non-sync I/O
sys/types.h,sys/time.h,unistd.h
int select( int numfds, fd_set *readfds, fd_set *writefds, fd_set *exeptfds, struct timeval *timeval )
numfds: the file's max number+1
readfds:the set of read files
writefds:the set of write files
exeptfds:the set of exept files
timeout: NULL;wait always
VALUE;some time
0:never wait
FD_ZERO( fd_set *set )
FD_SET( int fd, fd_set *set )
FD_CLR( int fd, fd_set *set )
FD_ISSET( int fd, fd_set *set )
TEXT FILE I/O
stdio.h
FILE *fopen( const char *path, const char *mode )
FILE *fdopen( itn fd, const char *mode )
FILE *freopen( const char *path, const char *mode, FILE *stream )
int fclose( FILE *stream )
size_t fread( void *ptr, size_t size, size_t nmemb, FILE *stream )
size_t fwrite( const void *ptr, size_t size, size_t nmemb, FILE *stream )
int getc( FILE *stream )
int fgetc( FILE * stream )
int getchar( void )
int putc( FILE *stream )
int fputc( FILE *stream )
int putchar( int c )
char *gets( char *s )
char fgets( char *s, int size, FILE *stream )
int puts( const char *s )
int fputs( const char *s, FILE *stream )
int scanf( const char *format, ... )
int fscan( FILE *fp, const char *format, ... )
int sscanf( char *buf, const char *format, ... )
int printf( const char *format,... )
int fprintf( FILE *fp, const char *format, ... )
int sprintf( char *buf, const char *format, ... )