本周学习概况
● 系统调用
● 标准I/O库
● 进程控制
● 进程间通信:管道、命名管道、消息队列
● 信号的基本操作
● 线程的基本操作
具体内容如下:
● 系统调用
基本命令
#who
作用: 显示登陆用户名,终端名,登陆时间
#open
作用 : 打开一个文件
头文件 #include <fcntl.h>
原型 int open(char *name, int how)
#close
作用:关闭一个文件
头文件: #include <unistd.h>
原型: int close(int fd)
#read
把指定数目的数据读到缓冲区
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count)
● 标准I/O库
以下的库函数均为#include<stdio.h>
打开和关闭流
FILE* fopen(const char *path, const char *mode);
int fclose(FILE *stream);
每次一个字符的I/O
int getc(FILE *fp)
int fgetc(FILE *fp)
int getchar(void)
int putc(int c, FILE *fp)
int fputc(int c, FILE *fp)
int putchar(int c)
每次一行的I/O
char *fgets(char *buf, int n, FILE *fp)
char *gets(char *buf)
int fputs(const char *str, FILE *fp)
int puts(const char *str)
数据块I/O
size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp)
size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp)
定位流
long ftell(FILE *fp)
int fseek(FILE *fp, long offset, int whence)
void rewind(FILE *fp)
int fgetpos(FILE *fp, fpos_t *pos)
int fsetpos(FILE *fp, fpos_t *pos)
格式化输出
int printf(const char *format, …)
int fprintf(FILE *fp, const char *format, …)
int sprintf(char *buf, const char *format, …)
int snprintf(char *buf, size_t n, const char *format,…)
格式化输入
int scanf(const char *format,…)
int fscanf(FILE *fp, const char *format,…)
int sscanf(const char *buf, const char *format,…)
文件流的检测
int feof(FILE *fp)
int ferror(FILE *fp)
●进程控制
fork函数:创建一个新进程
#include <unistd.h>
pid_t fork(void)
vfork函数:创建一个新进程
#include <unistd.h>
pid_t vfork(void);
exec函数
int execl(const char *path, const char *arg0, … ,(char *)0 )
int execv(const char *path, char *const argv[])
int execle(const char *path, const char *arg0, … ,(char *)0, char *const envp[] )
int execve(const char *path, char *const argv[], char *const envp[])
int execlp(const char *filename, const char *arg0, …, (char *)0 )
int execvp(const char *filename, char *const argv[])
wait和waitpid函数
#include <sys/wait.h>
pid_t wait(int *status)
pid_t waitpid(pid_t pid, int *status, int options)
exit与_exit函数
#include <stdlib.h>
void exit(int status)
void _exit(int status)
sleep函数
unsigned int sleep(unsigned int sec)
●进程间通信
pipe管道的创建
#include <unistd.h>
int pipe(int filedes[2]);
fifo有名管道的创建
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode)
消息队列的创建、发送、接收、控制消息
int msgget(key_t key, int flag);
key要通过函数ftok来生成唯一的值.
key_t ftok(char *pathname, int projid);
int msgsnd(int msqid, const void *ptr, size_t nbytes, int flag);
struct msgbuf{
long mtype; //消息类型
char mtext[1] //消息正文
}
ssize_t msgrcv(int msqid, void *ptr, size_t nbytes, long type, int flag)
int msgctl(int msqid, int cmd, struct msqid_ds *buf)
● 信号的基本操作
kill 传送信号
int kill(pid_t pid, int sig)
raise 传送信号
int raise(int sig)
alarm 信号时钟
unsigned int alarm(unsigned int seconds)
pause 挂起信号
int pause(void)
signal安装信号函数
#include <signal.h>
void (*signal(int signo, void (*func)(int) ) )(int)
信号集函数组有如下几个函数:
初始化信号集合set并将set设置为空.
int sigemptyset(sigset_t *set)
初始化信号集合, 将信号集合设置为所有信号的集合
int sigfillset(sigset_t *set)
将信号signo加入到信号集合之中.
int sigaddset(sigset_t *set, int signo)
信号signo从信号集合中删除.
int sigdelset(sigset_t *set, int signo)
查询信号是否在信号集合之中
int sigismember(sigset_t *set, int signo)
sigprocmask函数的作用是将指定的信号集合set加入到进程的信号阻塞集合之中,或从中删除。
int sigprocmask(int how, const sigset_t *set, sigset_t *oset)
● 线程的基本操作
线程的创建
#include <pthread.h>
int pthread_creat(pthread_t *thread, pthread_att_t *attr, void *(*start_rtn)(void*), void *arg)
线程的终止
#include <pthread.h>
void pthread_exit(void *rval_ptr);
等待线程的终止
void pthread_join(pthread_t thread, void **rval_ptr)
请求取消同一进程中的其他线程
#include <pthread.h>
void pthread_cancel(pthread_t tid)
线程清理处理程序
#include <pthread.h>
void pthread_cleanup_push(void(*rtn)(void *),void *arg);
void pthread_cleanup_pop(int execute);
定义互斥锁
#include<pthread.h>
pthread_t mutex;
初始化一个互斥锁
#include <pthread.h>
Int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
清除一个互斥锁
int pthread_mutex_destroy( pthread_mutex_t *mutex)
对互斥锁进行加锁
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)
对互斥锁解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex)
信号量
PV操作
sem_init用于创建一个信号量,并能初始化它的值
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value)
sem的定义 sem_t sem;
P操作
#include <pthread.h>
int sem_wait(sem_t *sem)
int sem_trywait(sem_t *sem)
V操作
#include <pthread.h>
int sem_post(sem_t *sem)
int sem_getvalue(sem_t *sem)
int sem_destroy(sem_t *sem)
主要的练习:
标准I/O:
练习1:
1.定义一个utmp结构体变量A
2.打开utmp文件
3.从utmp文件中读取一个结构体变量的内容到A中
4.显示A.ut_user的内容
5.重复3.4步,知道把utmp文件的内容读完。
练习2:
1. fread、fwrite: 用fopen、fread、fclose实现who命令。
2. fseek : 使用fseek定位到utmp文件的倒数第四个用户信息出开始读取。
5.fsetpos,fgetpos、用fsetpos实现2中的功能
3. sprintf atoi : 使用sprint atoi来实现数据类型的转换(整形到字符串、字符到整形),显示或用gdb调试,观察数据。
4. fprintf、fscanf: 使用fprint实现将who命令中的输出信息存入文件。
6.实现IP地址(字符串)和整形数据(4个int型数据)之间的转换:用sscanf 、sprintf 实现
char *host=“192.168.220.5”;
int p1;
int p2;
int p3;
int p4;
转换后:p1=192; p2=168; p3=220; p4=5
分别实现:(1)IP->整形 (2)整形->IP
进程练习:
1.在主进程中用fork创建另一个进程
在主进程中输出 “in main process”,并输出其pid号
在子进程中输出 “in sub process”,并输出其pid号
2.在主进程中用vfork 创建另一个进程,在子进程中对全局变量做改变,观察主进程中的输出;并与用fork 创建的子进程作比较。
3. 用execl 调用 “ls -a”命令。
例:execl("/bin/ls", "ls","-l","-a",(char *)0);
char argv[]={"ls","-l","-a",(char *)0};
execv("/bin/ls",argv);
4. 写一个简单的shell脚本,并用execl调用。
5. 练习使用wait和waitpid函数,确定主进程在子进程之后退出;
6. 在主进程中创建2个子进程,第一个子进程等待2秒,第二个子进程等待3秒,主进程中用waitpid分别等待两个子进程退出,输出一些提示信息观察结果。
7. 区别exit(0)和_exit(0)观察下面两段程序的执行结果:
int main()
{ printf("this is a test/n")
printf("test exit fun");
exit(0);
}
int main()
{ printf("this is a test/n")
printf("test exit fun");
_exit(0);
}
进程间通信
1.用pipe实现“ls –al | more”。涉及的知识点:pipe、dup2、fork。程序名dup.c
2 .fifo 实现本机上的两终端的聊天通信。涉及的知识点:mkfiof、 fork 、open、 close、 read 、write、fgets。程序名 chat1.c
Chat2.c
3.消息队列实现本机上的两终端的聊天通信。涉及的知识点:msgget msgsnd msgrcv msgctl fork fgets.程序名msg_chat.c
信号的练习:
练习:fork创建2个进程,父进程用系统调用kill()向2个子进程分别发送16和17软中断信号,在子进程中用signal函数设置信号处理函数,pause等待到信号后dosomething结束。程序名:signal_ex.c。
线程的练习:
仓库,生产者,消费者的练习.涉及的知识点:互斥锁、PV操作。
程序名:semmphore.c。