Unix环境高级编程
马踏飞燕&lin_li
博客地址以迁移:https://linli1724647576.github.io/
展开
-
第七章_线程 : 线程和fork
线程和fork当线程调用fork函数时,就为子进程创建了整个进程地址空间的副本,子进程通过继承整个地址空间的副本,也会将父进程的互斥量、读写锁、条件变量的状态继承过来。也就是说,如果父进程中互斥量是锁着的,那么在子进程中互斥量也是锁着的(尽管子进程自己还没有来得及lock),这是非常不安全的,因为不是子进程自己锁住的,它无法解锁。子进程内部只有一个线程,由父进程中调用fork函数的线程副本构成。如果调用fork的线程将互斥量锁住,那么子进程会拷贝一个pthread_mutex_lock副本,这样原创 2020-12-14 22:41:57 · 481 阅读 · 0 评论 -
第七章_线程 : 线程属性、同步属性
线程属性默认属性可以解决大多数情况,但是如果对性能有更高的要求,就可以通过修改线程属性,降低线程栈的大小,来减少内存的使用。设置线程属性的结构体:typedef struct{ int detachstate; //线程分离状态 int schedpolicy; //线程调度策略 struct sched_param schedparam; //线程的调度参数 int inheritsched; //线程的继承性 int scope; //线程的作用原创 2020-12-13 10:08:59 · 269 阅读 · 0 评论 -
第七章_线程 : 线程的同步
线程属性默认属性可以解决大多数情况,但是如果对性能有更高的要求,就可以通过修改线程属性,降低线程栈的大小,来减少内存的使用。设置线程属性的结构体:typedef struct{ int detachstate; //线程分离状态 int schedpolicy; //线程调度策略 struct sched_param schedparam; //线程的调度参数 int inheritsched; //线程的继承性 int scope; //线程的作用原创 2020-12-06 21:37:31 · 233 阅读 · 0 评论 -
第七章_线程 : 线程的概念、创建与终止
线程的概念、创建与终止线程的概念在Linux下,能够把线程看做是最小的运行单位(进程内部运用多线程完毕任务)。而进程是最小的分配资源单位(系统以进程为单位来创建,而没有创建一个线程来运行的说法)。实际上,不管是创建进程的fork,还是创建线程的pthread_create,底层的实现都是调用同一个内核函数clone。假设复制对方的地址空间。那就会产生一个”进程”。假设共享对方的地址空间,就产生一个”线程”。进程能够看作是仅仅有一个线程的进程。由于。linux内核不区分进程和线程,仅仅在用户层面上区分。原创 2020-12-06 21:02:33 · 379 阅读 · 0 评论 -
第六章_信号 : 函数sigsetjmp和siglongjmp
函数sigsetjmp和siglongjmp在信号处理程序中经常调用longjmp函数以返回到程序的主循环中,而不是从该处理程序返回。但是,调用longjmp有一个问题。当捕捉到一个信号时,进入信号捕捉函数,此时当前信号被自动地加到进程的信号屏蔽字中。这阻止了后来产生的这种信号中断该信号处理程序。(仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值)如果用longjmp跳出信号处理程序,那么,对此进程的信号屏蔽字会发生什么呢?(setjmp和longjmp保存和恢复信号屏蔽字,还是不保存和恢复,不原创 2020-11-30 20:00:56 · 1792 阅读 · 1 评论 -
第六章_信号 : 信号集和可靠信号机制
信号集的处理函数阻塞信号实际执行信号的处理动作称为信号递达(Delivery)信号从产生到递达之间的状态,称为信号未决(Pending)。进程可以选择阻塞 (Block )某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作.注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该原创 2020-11-30 19:19:29 · 314 阅读 · 0 评论 -
第六章_信号 : 信号的发送接收机制:具有超时功能的API
具有超时功能的API常见的低速系统调用包括➢ 读写(read、write)管道、终端设备、网络➢ 打开(open)终端设备等➢ pause、wait函数➢ 某些ioctl操作➢ 某些进程间通信函数➢ 注意:磁盘I/O并不属于这类低速系统调用。因为只要不是硬件错误,I/O操作总会返回。带有超时功能的read函数#include<stdio.h>#include<signal.h>#include<unistd.h>#include<stdl原创 2020-11-23 16:50:41 · 224 阅读 · 0 评论 -
第六章_信号 : 函数sleep
函数sleep该函数用于让调用进程挂起,直到➢ 已经过了指定的时间,或者➢ 调用进程捕捉到一个信号,并从信号处理程序返回#include <unistd.h>unsigned int sleep(unsigned int seconds);返回值:➢ 若已经过了指定的时间,则返回0➢ 若调用进程捕捉到一个信号,并从信号处理程序返回,则sleep提前返回,返回值是未睡够的秒数示例程序#include <stdio.h>#include <stdlib.h&原创 2020-11-22 15:44:25 · 272 阅读 · 0 评论 -
第六章_信号 : 函数alarm和pause
函数alarm和pause函数alarm使用alarm函数可以设置一个计时器,在将来某个指定的时间,该计时器会超时。当计时器超时时,产生SIGALRM信号。如果不忽略或不捕捉此信号,则其默认动作是终止调用该alarm函数的进程。#include <unistd.h>unsigned int alarm( unsigned int seconds );返回值:0或以前设置的闹钟时间的余留秒数其中,参数seconds的值是秒数,经过了指定的seconds秒后会产生信号SIGALRM。要原创 2020-11-22 14:40:41 · 298 阅读 · 0 评论 -
第六章_信号 : 函数kill和raise
函数kill和raisekill函数将信号发送给进程或进程组。raise函数则允许进程向自身发送信号。#include <signal.h>int kill(pid_t pid, int signo);int raise(int signo);两个函数返回值:若成功则返回0,若出错则返回-1调用raise(signo);等价于调用kill(getpid(), signo);kill的pid参数有4种不同的情况:进程将信号发送给其他进程需要权限:超级用户可将信号发送原创 2020-11-22 10:49:06 · 285 阅读 · 0 评论 -
第六章_信号 : signal函数--信号
signal函数–信号常见的信号类型signal信号机制是属于计算机异常处理机制中的一种。signal信号属于一种异步处理异常的机制之一。类似于我们平常在命令行上对于死循环的程序,按下ctrl-z暂时挂起,ctrl-c程序终止,这些挂起,终止信号都属于signal信号的一种,常见的几种signal信号如下图所示(供查询使用,平时并无用):常见的信号如下:发送信号常用的方法通过/bin/kill程序发送信号:/bin/kill -9 15213发送信号给进程15213/bin/kil原创 2020-11-22 01:51:36 · 4318 阅读 · 0 评论 -
第六章_信号 : 函数psignal和strsignal
函数psignal和strsignalpsignal函数#include <signal.h>void psignal(int signo, const char *msg);功能:该函数可移植地打印信号编号与对应的字符串,常用来输出信号的出错消息参数 参数1:信号编号 参数2:自定义的字符串(通常为程序名)打印的样式:字符串msg在最前面,后面跟一个冒号加一个空格,后面再加上对该信号的说明,最后是一个换行符msg: 信号说明\n如果msg为NULL,则只原创 2020-11-22 01:02:07 · 1672 阅读 · 0 评论 -
第五章_进程 : 进程,进程组,会话关系
进程进程是操作系统的一个核心概念。每个进程都有自己唯一的标识:进程ID,也有自己的生命周期。一个典型的进程的生命周期如图4-1所示。进程都有父进程,父进程也有父进程,这就形成了一个以init进程为根的家族树。除此以外,进程还有其他层次关系:进程、进程组和会话。进程组和会话在进程之间形成了两级的层次:进程组是一组相关进程的集合,会话是一组相关进程组的集合。这样说来,一个进程会有如下ID:·PID:进程的唯一标识。对于多线程的进程而言,所有线程调用getpid函数会返回相同的值。·PGID:进程组原创 2020-11-18 23:03:55 · 1118 阅读 · 0 评论 -
第五章_进程 : 函数system
函数system函数原型#include<stdlib.h>int system(const char * command)函数功能执行 dos(windows系统) 或 shell(Linux/Unix系统) 命令,参数字符串command为命令名。另,在windows系统下参数字符串不区分大小写。说明:在windows系统中,system函数直接在控制台调用一个command命令。在Linux/Unix系统中,system函数会调用fork函数产生子进程,由子进程来执行com原创 2020-11-10 23:02:49 · 149 阅读 · 0 评论 -
第五章_进程 : 函数setuid、setgid
函数setuid、setgid #include <sys/types.h>#include <unistd.h>int setuid(uid_t uid);int setgid(gid_t gid);改变用户/组ID的规则1、若进程具有超级用户权限,则setuid将实际用户ID、有效用户ID、保存的设置用户ID设置为uid2、若进程没有超级用户权限,但uid等于实际用户ID或保存的设置用户ID,则setuid只将有效用户ID设置为uid,不改变实际用户ID和保存的设原创 2020-11-10 22:59:01 · 599 阅读 · 0 评论 -
第五章_进程 : 函数exec函数族
函数execve#include<unistd.h>int execve(const char *filename, char *const argv[], char *const envp[]); execve() – 叫做执行程序函数就像Python中的os.system(cmd)这个函数,我们可以用这个函数来执行我们的shell脚本,单独的shell命令,或者是调用其他的程序,我们的execve()这个函数就和Python中的os.system函数类似,可以调用其他程序的执行,执原创 2020-10-27 22:02:49 · 243 阅读 · 0 评论 -
第五章_进程 : 函数wait和waitpid
函数wait和waitpid函数wait#include <sys/types.h> /* 提供类型pid_t的定义 */#include <sys/wait.h>pid_t wait(int *status)进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止原创 2020-10-27 22:32:27 · 278 阅读 · 0 评论 -
第五章_进程 : 函数fork
函数fork详情请参考fork的详细用法一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。#include<unistd.h>#include<s原创 2020-10-27 21:42:15 · 146 阅读 · 0 评论 -
第五章_进程 : 函数setjmp和longjmp
函数setjmp和longjmp非局部跳转语句—setjmp和longjmp函数。非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。#includeInt setjmp(jmp_buf env); 返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值Void longjmp(jmp_buf env,int val);在希望返回到的位置处调用setjmp,此位置在main函数中,因为直接调用原创 2020-11-02 20:19:53 · 231 阅读 · 0 评论 -
第五章_进程 : 函数exit、_exit和atexit
函数exit、_exit和atexit函数exit和_exit从图中可以看出,_exit 函数的作用是:直接使进程停止运行,清除其使用的内存空间,并清除其在内核的各种数据结构;exit 函数则在这些基础上做了一些小动作,在执行退出之前还加了若干道工序。exit() 函数与 _exit() 函数的最大区别在于exit()函数在调用exit 系统调用前要检查文件的打开情况,把文件缓冲区中的内容写回文件。也就是图中的“清理I/O缓冲”。#include<stdlib.h>void exit原创 2020-11-02 15:19:27 · 365 阅读 · 0 评论 -
第五章_进程 : Unix系统环境变量
函数getenv和putenv等Unix系统的环境变量Unix是一个多用户的操作系统,每个用户登录系统之后,都会有一个专用的运行环境。通常每个用户默认的环境都是相同的。这个默认的环境实际上就是一组环境变量的定义,用户可以对自己的运行环境进行定制,其方法就是修改相应的系统环境变量。环境变量一般用大写加下划线命名(例如,PATH、ORACLE_HOME )。环境变量就相当于一个指针,当我们要查看指针所指向的值的时候需要解引用。同样的,当我们想要查看环境变量里面的值的时候,需要在前面加 $ 引用。linu原创 2020-11-02 15:51:56 · 703 阅读 · 0 评论 -
实验二 目录树的遍历
实验二 目录树的遍历背景正确理解程序4-22。程序4-22递归降序遍历目录层次结构,并按照文件类型进行计数。主要涉及到三个函数myftw()、dopath()和myfunc()。myftw ()函数以所带参数pathname为要遍历的起始目录,计算出该目录下各种不同类型的文件的个数和所占百分比,并显示出来。它调用了另外两个函数,一个是dopath()函数,这是一个递归函数,对指定的起始目录下的每个目录项,按深度优先进行遍历;而对所访问的节点,则调用myfunc()进行处理。main函数输出统计结果。三个原创 2020-10-24 16:17:43 · 1019 阅读 · 0 评论 -
实验一 同步与异步write的效率比较
实验一 同步与异步write的效率比较一、程序要求实验要求程序必须指定输出的文件名,而该文件是否按同步方式打开,则是可以选择的。因此程序至少带一个、至多两个输入参数。程序默认从标准输入STDIN_FILENO读取输入文件,可以利用shell的输入定向功能选择具体的输入文件。timewrite < outfile > [sync]不得变更程序的名字和使用方法。sync参数为可选,若有则输出文件用O_SYNC打开(见课本P51的解释)。例:timewrite <f1 f2原创 2020-10-24 16:11:52 · 1497 阅读 · 0 评论 -
第四章_标准I/O、数据文件和信息 : 口令读取函数
口令读取函数 Unix口令文件 如果知道一个用户的用户ID或者登录名,可以通过getpwuid或getpwnam函数获得用户的登录信息.#include <pwd.h>#include <sys/types.h>struct passwd *getpwnam(const char *name);struct passwd *getpwuid(uid_t uid); The passwd structure is defined in <pwd.h> as原创 2020-10-19 14:57:39 · 114 阅读 · 0 评论 -
第四章_标准I/O、数据文件和信息 : 函数tmpnam、tmpfile
函数tmpnam、tmpfile临时文件通常,程序需要以文件的形式使用临时存储。这也许是存储计算的中间结果,或者是在实际操作之前所做的文件拷贝备份。例如,一个数据程序在删除记录时会使用临时文件。文件会收集需要保存的数据库实体,然后在操作结束时,临时文件会成为新的数据库而原始的会被删除。临时文件的大量使用隐藏了他的一个缺点。我们必须小心来确保程序会选择一个唯一的名字来使用临时文件。如果不是这样,因为Linux是一个多任务系统,也许会有另一个程序选择了相同的名字,而这两个彼此之间会相互影响。创建临时文件原创 2020-10-14 19:47:15 · 477 阅读 · 0 评论 -
第四章_标准I/O、数据文件和信息 : 格式化输入输出函数
格式化输入输出函数格式化IO输出int printf(const char* format, ....);int fprintf(FILE *fp, const char*format, ...);int sprintf(char *buf, const char*format, ...);(1)printf,是把格式化字符串输出到标准输出(一般是屏幕).(2)sprintf,是把格式化字符串输出到指定字符串,所以参数比printf多了个char * ,那就是目标字符串的地址.(3)fpri原创 2020-10-14 19:17:04 · 129 阅读 · 0 评论 -
第四章_标准IO、数据文件和信息 : 读写流函数
读写流函数对流有三种读写方式1、每次读写一个字符2、每次读写一行3、每次读写任意长度每次读写一个字符输入一个字符int getc(FILE *fp);int fgetc(FILE *fp);int getchar();成功返回欲读字符,若已处于文件尾或出错返回EOFgetchar()等同于getc(stdin)关于getc和fgetc的区别也不是很大,getc通常是宏,fgetc是函数getc和fgetc的区别 不管出错还是到达文件尾,都是返回EOF。如何区分?调用ferr原创 2020-10-14 13:29:17 · 140 阅读 · 0 评论 -
第四章_标准IO、数据文件与信息:函数fseek、ftell、rewind
函数fseek、ftellint fseek(FILE * _File, long _Offset, int _Origin); fseek函数是 用来设定文件的当前读写位置.函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere为基准,偏移offset(指针偏移量)个字节的位置,函数返回0。如果执行失败则不改变stream指向的位置,函数返回一个非0值。超出文件末尾位置,还是返回0。往回偏移超出首位置,还是返回0,小心使用。第一个参数stream为文件指针。原创 2020-10-14 09:25:19 · 180 阅读 · 0 评论 -
第四章_标准IO、数据文件和信息 : 函数fflush
函数fflush#include《stdio.h>int fflush(FILE *stream); 调用fflush()会将缓冲区中的内容写到stream所指的文件中去.若stream为NULL,则会将所有打开的文件进行数据更新fflush(stdin):刷新缓冲区,将缓冲区内的数据清空并丢弃fflush(stdout):刷新缓冲区,将缓冲区内的数据输出到设备测试函数#include<stdio.h>int main(){ printf("hello");原创 2020-10-13 23:25:47 · 140 阅读 · 0 评论 -
第四章_标准IO、数据文件和信息 :函数uname、gethostname
函数uname、gethostnameuname获取当前内核名称和其它信息。#include <sys/utsname.h>int uname(struct utsname *buf);参数:buf:指向存放系统信息的缓冲区,原型如下struct utsname { char sysname[]; char nodename[]; char release[]; char version[]; char machine[]; #if原创 2020-10-19 15:13:27 · 121 阅读 · 0 评论 -
第四章_标准IO、数据文件和信息 : 函数fopen、freopen、fdopen and fclose
函数fopen、freopen、fdopen and fclose打开流#include <stdio.h>FILE *fopen(const char *path, const char *mode);FILE *fdopen(int fd, const char *mode);FILE *freopen(const char *path, const char *mode, FILE *stream);int fclose(FILE *fp);fopen打开指定的文件fr原创 2020-10-13 23:05:48 · 275 阅读 · 0 评论 -
第四章_标准IO、数据和文件信息 : 函数setbuf、setvbuf
函数setbuf、setvbuf函数setbuf()用于将指定缓冲区与特定的文件流相关联,实现操作缓冲区时直接操作文件流的功能。#include <stdio.h>void setbuf(FILE * stream, char * buf);测试代码观察缓冲区与流关联后的影响#include <stdio.h> char outbuf[BUFSIZ]; int main(void) { setbuf(stdout, outbuf); // 把缓冲区与流相连原创 2020-10-13 22:43:51 · 283 阅读 · 0 评论 -
第三章_文件和目录 : 函数chdir、fchdir 和 getcwd
函数chdir、fchdir 和 getcwd每个进程都有一个当前工作目录,此目录是搜索所有相对路径名的起点(不以斜杠开始的路径名为相对路径名)。当用户登录到 *NIX 系统时,其当前工作目录通常是口令文件(/etc/passwd)中该用户登录项的第 6 个字段–用户的起始目录(home directory)。当前工作目录是进程的一个属性,起始目录则是登录名的一个属性。进程调用chdir或fchdir函数更改当前工作目录的函数。#include unistd.h>int chdir(const原创 2020-10-09 22:31:45 · 280 阅读 · 0 评论 -
第三章_文件和目录 : 函数opendir、readdir、closedir
函数opendir、readdir、closedir#include <sys/types.h> #include <dirent.h> DIR *opendir(const char *name);struct dirent * readdir(DIR * dir); int closedir(DIR *dir);opendir()用来打开参数name 指定的目录, 并返回DIR*形态的目录流, 和open()类似, 接下来对目录的读取和搜索都要使用此返回值.D原创 2020-10-09 21:57:59 · 281 阅读 · 0 评论 -
第三章_文件和目录 : 函数mkdir、mkdirat和rmdir
函数mkdir、mkdirat和rmdirmkdir 是用来创建一个空目录的,而 rmdir 用来删除空目录。与 linux 命令的 mkdir不同的是,mkdir 函数需要指定目录的权限位。目录的权限位目录的权限位,至少要设置一个执行许可位。即 rwx 中的那个 x 位。如果不设置,就没办法使用 cd 命令进入目录,也无法读取目录下的文件内容。所以,这个位是必须的。目录的写权限位。如果未设置写权限位(w 位),将导致无法向目录文件中写入目录项(dir_entry 结构)。比如不能使用 touch原创 2020-10-09 21:32:23 · 323 阅读 · 0 评论 -
第三章_文件与目录 : 函数symlink、symlinkat和readlink、readlinkat
函数symlink、symlinkat和readlink、readlinkat#include<unistd.h>int symlink(const char*actualpath,const char *sympath);int symlinkat(const char *actualpath,int fd,const char *sympath); 两个函数返回值:若成功,返回0;若出错,返回-1ssize_t readlink(原创 2020-10-09 20:31:08 · 1144 阅读 · 0 评论 -
第三章_文件和目录 : 函数rename和renameat
函数rename和renameat文件或目录可以用rename函数或者renameat函数进行重命名。#include <stdio.h>int rename(const char * oldname, const char * newname);int renameat(int oldfd, const char *oldname, int newfd, const char *newpath); 两原创 2020-10-09 16:59:33 · 666 阅读 · 0 评论 -
第三章_文件和目录 : 函数link、linkat、unlink、unlinkat和remove
硬链接&软连接函数link、linkat、unlink、unlinkat和remove任何一个文件可以有多个目录项指向其i节点。创建一个指向现有文件的链接的方法是使用link函数或linkat函数。#include <unistd.h>int link(const char *existingpath, const char * newpath);int linkat(int efd, const char *existingpath, int nfd, const char原创 2020-10-09 16:32:07 · 887 阅读 · 0 评论 -
第三章_文件与目录 : 函数truncate、ftruncate
函数truncate、ftruncate#include<unistd.h>#include<sys/types.h>int truncate(const char *path,off_t length);int ftruncate(int fd,off_t length);truncate()和ftruncate()函数导致一个名称为path或者被文件描述符fd引用的常规文件被截断成一个大小精为length字节的文件。如果先前的文件大于这个大小,额外的数据丢失。如果先原创 2020-10-09 16:02:03 · 278 阅读 · 0 评论 -
第三章_文件与目录 : 函数chown 、lchown、fchown
函数chown 、lchown、fchown使用ls –l命令会给出文件的所有者和文件所有者所处的组。可以通过函数chown、fchown和lchown函数来修改文件所有者和文件所有者所属的组,具体如下:#include <unistd.h>int chown(const char *pathname,uid_t owner,gid_t group);int fchown(int fd,uid_t owner,gid_t group);int fchownat(int fd,const原创 2020-10-09 15:41:53 · 698 阅读 · 0 评论