第7章 Linux环境编程
主要内容 系统调用和库函数简介 文件操作 进程管理和同步 进程通信 内存管理
7.1 系统调用和库函数 7.1.1 系统调用 系统调用是操作系统提供的、与用户程序之间的接口,也就是操作系统提供给程序员的接口 7.1 系统调用和库函数 7.1.1 系统调用 系统调用是操作系统提供的、与用户程序之间的接口,也就是操作系统提供给程序员的接口 从感觉上系统调用类似于过程调用,都由程序代码构成,使用方式相同 两者有实质差别:过程调用只能在用户态下运行,不能进入核心态;而系统调用可以实现从用户态到核心态的转变。 系统调用可大致分为五个类别:进程控制、文件管理、设备管理、信息维护和通信
7.1.2 库函数 7.1.2 库函数 它们本身并不属于操作系统的内核部分 库函数可以分为下面六大类: 7.1.2 库函数 它们本身并不属于操作系统的内核部分 库函数可以分为下面六大类: ① 文件管理 ② 状态信息 ③ 文件修改 ④ 程序设计语言的支持 ⑤ 程序装入和执行 ⑥ 通信 7.1.2 库函数
7.1.3 调用方式 例如,open系统调用可以打开一个指定文件,其函数原型说明如下: 7.1.3 调用方式 例如,open系统调用可以打开一个指定文件,其函数原型说明如下: #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *path, int oflags); 不同的系统调用所需要的头文件(又称前导文件)是不同的。
7.2 文 件 操 作 7.2.1 有关文件操作的系统调用 常用的有关文件操作的系统调用有:creat,open,close,read,write,lseek,link,unlink,mkdir,rmdir,chdir,chmod等 例如: #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int creat(const char *pathname, mode_t mode); int open(const char *path, int oflags); int open(const char *path, int oflags, mode_t mode);
7.2.2 应用示例 /* rdwr.c-The read and write system calls */ 7.2.2 应用示例 /* rdwr.c-The read and write system calls */ #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> int main(void) { int fd1,fd2,fd3,nbytes; int flags=O_CREAT|O_TRUNC|O_WRONLY; char buf[10]; if((fd1=open("rdwr.c",O_RDONLY,0644))<0){ perror("open rdwr.c"); exit(EXIT_FAILURE); } if((fd2=open("/dev/null",O_WRONLY))<0){ perror("open /dev/null"); if((fd3=open("/tmp/foo.bar",flags,0644))<0){ perror("open /tmp/foo.bar"); close(fd1); close(fd2); exit(EXIT_FAILURE); } while((nbytes=read(fd1,buf,10))>0){ if(write(fd2,buf,10)<0) perror("write /dev/null"); if(write(fd3,buf,nbytes)<0) perror("write /tmp/foo.bar"); write(STDOUT_FILENO,buf,10); close(fd3); exit(EXIT_SUCCESS);
7.3 进 程 控 制 7.3.1 有关进程控制的系统调用 常用的有关进程控制的系统调用有:fork,exec,wait,exit,getpid,sleep,nice等 例如: #include <unistd.h> #include <sys/types.h> pid_t fork(void); pid_t getpid(void); pid_t getppid(void);
7.3.2 应用示例 else if(child==0){ /*此时是子进程被调度运行*/ /*proc1.c演示有关进程操作*/ 7.3.2 应用示例 else if(child==0){ /*此时是子进程被调度运行*/ old_ppid=getppid(); sleep(2); new_ppid=getppid(); } else { sleep(1); exit(0); /*父进程退出*/ /*下面仅子进程运行*/ printf("Original parent:%d\n",parent); printf("Child:%d\n",getpid()); printf("Child's old ppid:%d\n",old_ppid); printf("Child's new ppid:%d\n",new_ppid); exit(0); /*proc1.c演示有关进程操作*/ #include <unistd.h> #include <sys/types.h> #include <stdio.h> #include <errno.h> int main(int argc,char **argv) { pid_t pid,old_ppid,new_ppid; pid_t child,parent; parent=getpid(); /*获得本进程的PID*/ if((child=fork())<0){ fprintf(stderr,"%s:fork of child failed:%s\n",argv[0],strerror(errno)); exit(1); }
7.4 进 程 通 信 Linux下进程间通信的几种主要手段是:管道(pipe)及有名管道(named pipe)、信号(signal)、消息(message)、共享内存(shared memory)、信号量(semaphore)和套接口(socket)。 7.4.1 有关进程通信的函数 例如: #include <unistd.h> int pipe(int filedes[2]); #include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode);
7.4.2 应用示例 /*pipedemo.c演示使用管道机制进行I/O控制*/ #include <unistd.h> 7.4.2 应用示例 /*pipedemo.c演示使用管道机制进行I/O控制*/ #include <unistd.h> #include <stdio.h> #include <errno.h> int main(int argc,char **argv) { static const char mesg[]="Happy New Years to you!"; char buf[BUFSIZ]; size_t rcount,wcount; int p_fd[2]; size_t n; if(pipe(p_fd)<0){ /*创建管道*/ fprintf(stderr,"%s:pipe failed:%s\n",argv[0],strerror(errno)); exit(1); } printf("Read end=fd %d,write end=fd %d\n",p_fd[0],p_fd[1]); n=strlen(mesg); if((wcount=write(p_fd[1],mesg,n))!=n){ /*写入数据*/ fprintf(stderr,"%s:write failed:%s\n",argv[0],strerror(errno)); exit(1); } if((rcount=read(p_fd[0],buf,BUFSIZ))!=wcount){ /*读出数据*/ fprintf(stderr,"%s:read failed:%s\n",argv[0],strerror(errno)); buf[rcount]='\0'; printf("Read <%s> from pipe\n",buf); close(p_fd[0]); close(p_fd[1]); return 0;
7.5 内 存 管 理 #include <stdlib.h> void *malloc(size_t size); 7.5 内 存 管 理 #include <stdlib.h> void *malloc(size_t size); void *calloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); void free(void *ptr);
7.6 综合编程示例 Shell命令 可执行的C程序 系统调用 system函数