编程语言应用

首页 » 常识 » 常识 » unix环境C语言编程指导
TUhjnbcbe - 2023/10/6 19:14:00

goto语句不能跨越函数,setjumplongjmp可以处理嵌套调用中出错情况。在希望返回的位置intsetjmp(jmp_bufenv),出错位置intlongjmp(env,8)。“str1”“str2”等价于”str1str2”。为IO库分配缓冲区应全局静态或动态alloc分配。编译器进行优化时,它有时会取一些值的时候,直接从寄存器里进行存取,而不是从内存中获取,这种优化在单线程的程序中没有问题,但到了多线程程序中,由于多个线程是并发运行的,就有可能一个线程把某个公共的变量已经改变了,这时其余线程中寄存器的值已经过时,但这个线程本身还不知道,以为没有改变,仍从寄存器里获取,就导致程序运行会出现未定义的行为。自动变量不想回滚,可以定义为volatite属性。易失属性告诉编译器不要优化,在其他地方会改变值,优化可能将这个变量一直放到寄存器中。intgetrlimit(intresource,structrlimit*rlptr)setrlimit可以查询和更改资源限制。shell中的ulimit。getpidgetppidgetuidgeteuidgetgidgetegidpid_tfork(void)fork返回两次clone,父返子,子返0.父子进程执行fork之后的代码,父子共享正文不共享数据,共享文件表和i节点。写时复制(copy-on-write)写时复制,只读时共用。vfork在子进程调用exec或exit之前,他在父进程的空间中运行,调用exec或exit之后父进程才继续运行。标准IO库printf是带缓冲的。标准输出连到终端是行缓冲,否则是全缓冲。定向到文件是全缓冲信号可由进程自身产生、其他进程或内核产生。父进程提前终止的的子进程由init进程领养。内核为每个终止的子进程保存了一定量的信息,父进程用wait或waitpid得到这些信息。一个长期运行的进程fork很多子进程,除非手动wait,否则会出现很多僵死进程。pid_twait(intstatloc)pid_twaitpid(pid_tpid,intstatloc,intoptions)。如果收到SIGCHLD信号调用wait,可以立刻返回,如果任意时刻调wait,可能会阻塞直到有一个子进程终止。wait3wait4比waitpid多了一个功能是最后一个参数会返回所有子进程使用资源情况的汇总。竞争条件:多进程处理共享数据,数据的结果和处理顺序有关。父等子死用wait,子等父死while(getppid()!=1)sleep(1);等于1是init进程id。为1说明父进程死了,被init接管了。exec不创建新进程,进程ID不变。exec只是用一个全新的程序替换当前进程的正文、数据、队、栈。execlexecvexecleexecveexeclpexecvp所有.c文件查找字符串abort的指令$grepabort.//.c任何时候都可以调用intsetuid(uid_tuid)做下两种操作:有效用户ID=实际用户ID;有效用户ID=保存的设置用户ID。设置用户ID的程序,fork后,exec之前要改回普通权限,不应使用system函数。suspend$fg作业控制shell中awk实际是shell先fork-exec(awk)-wait来运行的。char*getlogin(void)获取登录名。找到运行该程序的用户登录名getpwuid(getuid())网络登录telnetd进程fork,父负责网络连接的通信,子执行login,父子间通过伪终端相连接。进程组是一个或多个进程的集合。getpgidsetpgid设置指定进程或调用进程的组ID。会话是一个或多个进程组的集合。进程调用pid_tsetsid(void)建立一个新会话。进程是首进程、组长、断开所有控制终端。pid_tgetsid(pid_tpid)返回会话首进程的进程组ID。secureCRT是终端,对应前台进程组,控制进程组,后台进程组,加在一起是会话。一个作业是几个进程的集合,通常是一个进程的管道线。vimain.cpr*.c

lpr

makeall终端驱动程序产生信号进而影响前台进程组的方法:中断字符ctrl+C退出字符ctrl+\挂起字符ctrl+Z。可以用信号使后台作业暂停,fg%1使1号作业转为前台作业进程属于进程组,进程组属于一个会话,会话可能有也可能没有控制终端。前台进程组ID是终端的属性,不是进程的属性。管道线的最后一个进程是shell的子进程,执行管道的其他命令都是最后一个进程的子进程。前端进程组ID==sessionID时说明他是后台进程。不是孤儿进程组的条件:该进程组中有一个进程,其父进程属于同一个会话的另一个组。信号SIGKILLSIGSTOP不能忽略,不能捕捉。core文件复制进程终止时的存储映像。kill命令和kill函数只是将一个信号送给一个进程或组,进程是否终止取决于信号的类型,以及进程是否安排了捕捉该信号。$kill-USRvoid(signal(intsigno,void(func)(int)))(int)成功返回信号以前的处理配置,失败返回SIG_ERR。不改变信号的处理方式,就不能确定信号当前的处理方式。func指定SIG_IGN或SIG_DEL表示忽略或默认处理。exec使捕捉失效,捕捉函数的地址可能无意义。进程捕捉到信号执行信号处理函数func,执行完后执行发生信号时正在执行的代码。处理第一次信号后是否将信号动作复位为默认值?readwrite部分数据时被中断算成功还是失败可以选择。在信号处理程序中调用一个不可重入函数,结果是不可预见的。raise(intsigno)==kill(getpid(),intsigno)进程将信号发送给其他进程需要权限。向一个不存在的进程发空信号,kill返回-1.进程ID会重新使用。signal函数的语义与实现有关,最好使用sigaction函数。sigaction(signo,act,oact)sigemptyset(act.sa_mask)在处理一个给定的信号时,如果这种信号再次发生,通常并不将他们排队,会被阻塞到对前一个信号处理结束为止。阻塞结束后内核只传递这种信号一次。unix低速系统调用阻塞期间如果接受到一个信号,则该低速系统调用被中断。voidabort(void)使异常程序终止。子进程终止会向父进程发送SIGCHLD信号。sig2strstr2sig是信号编号和信号名相互转换函数。多线程程序在单处理器运行仍然能改善响应时间和吞吐量。线程ID只在它所属的进程环境中有效,因此可以不唯一。pthread_tpthread_self(void)获得自身线程的ID。主线程可以用线程ID控制哪个线程处理哪些作业。新线程和主线程之间有竞争,使用主线程返回的线程id并不安全。线程ID如果很长那估计是地址。如果任一线程调用exit,_Exit,_exit整个进程就会终止。线程终止方式:1.启动函数返回。2被同进程其他线程取消。3pthread_exitvoidpthread_exit(voidrval_ptr)intpthread_join(pthread_tthread,void*rval_ptr)线程里面声明的东西别往出带。线程从线程函数返回终止,清理程序就不被调用。waitpid==pthread_join。pthread_detach使线程分离,分离线程终止时资源被回收,分离的线程无法pthread_join。加锁的一种场景:对引用计数加1、减1以及检查是否为0之前都要锁住互斥量。读写锁以读模式锁住是共享模式,以写模式锁住是独占模式。线程的虚拟地址空间是多个线程共用,如果线程多,会不够用。递归类型互斥量可以递归加锁。线程和信号都涉及函数可重入的问题。信号:捕捉函数如果向全局数据写会错。线程:多个线程同时调用同一函数。每个线程有各自的信号屏蔽字。信号处理函数进程内共享。errno被重新定义为线程私有数据。键用来保护线程私有数据。包含多线程的进程fork时只有fork的线程被复制进子进程,锁的情况无法控制,如果马上exec就可以避免。pread(…)使偏移量的设置和数据读取成为一个原子操作。ps-axj创建守护进程两次fork,就不是会话首进程,不会取得控制终端。fork保证子进程不是进程组组长,可以setsid。lockfile(fd)对文件加锁lockf(lockfd,F_TLOCK,0L)可以确保只有一个守护进程运行。低速系统调用是可能会使进程永远阻塞的一类系统调用。非阻塞IO:操作无法完成,立即出错返回。两种方法指定描述符为非阻塞IO:open时O_NONBLOCK;fcntl(fd,cmd,lock)打开O_NONBLOCK标志。记录锁==字节范围锁:当一个进程读或修改文件某部分时,可以阻止其他进程修改同一文件区。有些系统中文件的最后状态取决于写该文件的最后一个进程。同一进程可对同一字节范围重复加锁,新锁换老锁。可以测试另一个进程是否对某记录加锁。锁是与进程、文件两者相关联的。fork出的子进程不继承父进程对文件的锁。exec新程序继承原程序的锁。某些unix提供系统调用跟踪特性。STREAM:构造内核设备驱动程序和网络协议包的一种通用方法。IO多路转接:执行阻塞read,阻塞是对整个进程阻塞,如果多个通路想要相互不影响,就得fork多个进程,每个进程处理各自的文件描述符。用非阻塞read轮询描述符消耗cpu。IO多路转接思想:构造一张描述符表,调用一个函数,直到表中描述符中的一个已经准备好IO时,该函数返回,告诉进程哪些描述符可以IO。主要用于终端IO和网络IO。select(0,NULL,NULL,NULL,tv)相当于sleep了,精确到微秒。异步IO:基本思想,告诉内核,当一个描述符已准备好可以进行IO时,用一个信号通知它。系统V异步IO调ioctl设置信号处理,只对STREAMS设备和STREAMS管道起作用。BSD异步IO设置信号SIGIO处理程序,调fcntl设置O_ASYNC文件为异步IO。只对终端和网络描述符有效。存储映射IO:unsignedcharmmapBuf=(unsignedchar)mmap(NULL,fileSize,PROT_READ,MAP_SHARED,fd,0)munmap((char*)mmapBuf,fileSize)msync冲洗到磁盘IPC:各种管道、消息队列、信号量、共享存储、套接字、STREAMS管道:半双工;只能在公共祖先的进程间使用,通常fork后父子间使用。intpipe(intfiledes[2])fork后f[0]--f[1]有两份,各关闭一个sh-ccmdstring表示shell将扩展字符串中的特殊字符。${PAGE:-more}如果PAGE已定义,使用,否则用more。对管道标准IO默认全缓冲。通过FIFO不相关的进程也能交换数据。intmkfifo(pathname,mode_tmode)类似于创建普通文件。创建IPC结构:msggetsemgetshmget要指定一个键key_t。ftok可由一个路径名和项目ID产生一个键key_tftok(path,id)msgctlsemctlshmctl修改uid、gid、mode三种IPC都有内置限制,可通过配置内核修改。ipcs查看ipcrm删除msgrcv可以是非先进先出信号量的值代表对应资源是否可以使用。semop(_ID,buf[],1)表示等待信号量、释放资源、获取资源。semctl取信号量信息、设置信号量信息。使用信号量,先创建一个包含一个成员的信号量集合,信号量值赋初值1.分配资源时sem_op为-1调用semop,释放资源sem_op为1调用semop。每次设置SEM_UNDO,以处理进程终止还有未释放资源的情况。shmget既可以创建,也可以引用已有的。shmctlIPC_RMID减少引用数,不真正删除。shmid和pickey不一样,shmget返回值是shmid。shmdt脱接不删除,引用数减一。套接字用于不同计算机上的进程相互通信,其它进程运行位置透明。可以采用许多网络协议,TCP/IP常见。创建一个套接字intsocket(intdomain,inttype,intprotocol)返回套接字文件描述符。intshutdown(intsockfd,inthow)禁止套接字上的输入输出。uint32_thtonl(uint32_thostint32)等进行处理器字节序和网络字节序的转换。inet_pton(AF_INET,host.c_str(),m_addr.sin_addr)将文本字符串转换成网络字节序的二进制地址pollselect函数能检查文件描述符的状态,用来决定是否对文件描述符执行某种操作。setsockopt(_sockfd,SOL_SOCKET,SO_SNDTIMEO,timeo,len)intfattach(intfileds,constchar*path)使STREAMS管道和文件系统中的一个名字关联。unix域套接字用于同一机器上进程间通信。intssocketpair(intdomain,inttype,intprotocol,intsockfd[2])终端IO:函数tcgetattrtcsetattr终端IO控制函数大多tc开头很多数据库实现都采用两个文件:索引文件和数据文件。

1
查看完整版本: unix环境C语言编程指导