/************************************************************/
*
* 文件和文件描述符操作的系统调用接口。
*
/************************************************************/
/*打开和关闭文件*/
/*
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, int flags, mode_t mode);
flag取值表
O_RDONLY 只读访问打开文件
O_WRONLY 只写访问打开文件
O_RDWR 读和写访问打开文件
O_CREAT 如果文件不存在则建立文件
O_EXCL 仅与O_CREAT连用,如果文件已存在,强制函数调用失败
O_NOCTTY 如果打开的文件是一个终端,就不会成为打开其进程的控制终端
O_TRUNC 如果文件存在,则将文件的长度截至0
O_APPEND 将文件指针设置到文件的结束处(如果打开来写)
O_NONBLOCK 如果读操作没有blocking(由于某种原因被拖延)则无法完成时,读操作返回0字节
O_NODELAY 同上
O_SYNC 在数据被物理的写入磁盘或其他设备之后操作才返回
mode说明
umask 新创建的文件和目录应关闭的权限位的位掩码,只影响文件的权限位,不能改变修饰位和文件类型。
bit15 bit14 bit13 bit112
文件类型位
bit11 bit10 bit9
修饰位(设置UID位 设置GID位 粘附位)
bit8 bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
所有者读写执行 本组人读写执行 其它人读写执行
#include <sys/stat.h>
mode_t umask(mode_t newmask);
功能:设置进程的umask为newmask并且返回进程目前的unmask;
参数:newmask IN 进程的新umask
返回:进程的当前umask;
说明:
用于该参数的宏定义
S_ISUID 0004000 设置UID位
S_ISGID 0002000 设置GID位
S_ISVTX 0001000 粘附位
S_IRWXU 00700 用户(所有者)具有读/写/执行权限
S_IRUSR 00400 用户(所有者)具有读权限
S_IWUSR 00200 用户(所有者)具有写权限
S_IXUSR 00100 用户(所有者)具有执行权限
S_IRWXG 00070 本组人具有读/写/执行权限
S_IRGRP 00040 本组人具有读权限
S_IWGRP 00020 本组人具有写权限
S_IXGRP 00010 本组人具有执行权限
S_IRWXO 00007 其它人具有读/写/执行权限
S_IROTH 00004 其它人具有读权限
S_IWOTH 00002 其它人具有写权限
S_IXOTH 00001 其它人具有执行权限
文件类型
S_IFMT 00170000 所有文件类型的位掩码
S_IFSOCK 0140000 套接口文件
S_IFLNK 0120000 符号链接文件
S_IFREG 0100000 普通文件
S_IFBLK 0060000 块设备文件
S_IFDIR 0040000 目录文件
S_IFCHR 0020000 字符设备文件
S_IFIFO 0010000 FIFO文件
STDIN_FILENO
STDOUT_FILENO
STDERR_FILENO
#include <unistd.h>
int close(int fd);
#include <unistd.h>
ssize_t read(int fd, const void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
把fd指定的文件设置为length长度,返回值0正常,-1出错并设置errno
#include <unistd.h>
int ftruncate(int fd, off_t length);
定位指针文件
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
功能:移动文件指针;
参数:fd,文件描述符 IN
offset 指针偏移 IN
whence 指针移动方式 IN
返回:指针移动后位置
说明:指针移动方式的设置
SEEK_SET 设置文件指针到文件的offset字节处
SEEK_CUR 设置文件指针到当前位置偏移offset字节处
SEEK_END 设置文件指针位置从文件尾往回offset字节处
文件信息的获取
命令:
stat filename
头文件:
#include <sys/stat.h>
#include <unistd.h>
函数:
int fstat(int fd,struct stat *buf);
功能:
参数:
返回:
说明:文件状态结构
struct stat
{
dev_t st_dev;
ino_t st_ino;
mode_t st_mode;/*文件类型*/
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
off_t st_size;/*文件长度*/
unsigned long st_blksize;
unsigned long st_blocks;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
}
对文件类型的操作:
S_ISLNK(mode) 符号链接文件
S_ISREG(mode) 普通文件
S_ISDIR(mode) 目录文件
S_ISCHR(mode) 字符设备文件_
S_ISBLK(mode) 块设备
S_ISFIFO(mode) FIFO
S_ISSOCK(mode) 套接口
改变文件所有权
#include <sys/types.h>
#include <unistd.h>
int fchown(int fd, uid_t owner, gid_t group);
改变文件读写权
#include <sys/types.h>
#include <sys/stat.h>
int fchmod(int fd, mode_t mode);
设置文件锁
读写锁设置:进程1设置读锁时,进程2可以设置读锁不能设置写锁
进程1设置写锁时,进程2不能设置读锁也不能设置写锁
参照程序实现。
复制文件描述符
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
*/
/*
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
*/
/*打开和关闭文件描述符*/
/*int main(void)
{
int fd;
char path[] = "hello";
if((fd = open(path,O_CREAT|O_TRUNC|O_WRONLY,0644))<0)
{
perror("open");
exit(EXIT_FAILURE);
}
else
{
printf("opened %s/n",path);
printf("descriptor is %d/n",fd);
}
if(close(fd)<0)
{
perror("close");
exit(EXIT_FAILURE);
}
else
{
printf("closed %s/n",path);
}
exit(EXIT_SUCCESS);
}*/
/*读写文件*/
/* if(write(STDOUT_FILENO, buf, 10)<0)
{
perror("write");
}*//*标准输出*/
/*
int main(void)
{
int fdsrc, fdnull, fdtmp, numbytes;
int flags = O_CREAT|O_TRUNC|O_WRONLY;
char buf[10];
if((fdsrc = open("putinout.c",O_RDONLY,0644))<0)
{
perror("open fdread.c");
exit(EXIT_FAILURE);
}
if((fdnull = open("/dev/null",O_WRONLY)) < 0 )
{
perror("open /dev/null");
close(fdsrc);
exit(EXIT_FAILURE);
}
if((fdtmp = open("/tmp/foo.bar", flags, 0644))<0)
{
perror("open /tmp/foo.bar");
close(fdsrc);
close(fdnull);
exit(EXIT_FAILURE);
}
while((numbytes = read(fdsrc, buf, 10)) > 0)
{
if(write(fdnull, buf, 10)<0)
{
perror("write /dev/null");
}
if(write(fdtmp, buf, numbytes)<0)
{
perror("write /tmp/foo.bar");
}
}
// ftruncate(fdtmp,100);
close(fdsrc);
close(fdnull);
close(fdtmp);
exit(EXIT_SUCCESS);
}
*/
/*
int main()
{
int fdsrc, fdnull, fdtmp, numbytes;
int flags = O_CREAT|O_TRUNC|O_WRONLY;
int i;
char buf[10];
if((fdtmp = open("/tmp/foo.bar", flags, 0644))<0)
{
perror("open /tmp/foo.bar");
close(fdsrc);
close(fdnull);
exit(EXIT_FAILURE);
}
numbytes = 10;
for(i=0;i<numbytes;i++)
{
buf[i] = i;
}
lseek(fdtmp, 10, SEEK_SET);
if(write(fdtmp, buf, numbytes)<0)
{
perror("write /tmp/foo.bar");
}
lseek(fdtmp, 10, SEEK_END);
if(write(fdtmp, buf, numbytes)<0)
{
perror("write /tmp/foo.bar");
}
}*/
/*多路选择*/
/*#define BUFSZ 1024
void err_quit(char * msg);
int main(void){
int fds[2];
char buf[BUFSZ];
int i,rc,maxfd;
fd_set watchset,inset;
if((fds[0]=open("pipe1", O_RDWR|O_NONBLOCK))<0)
err_quit("Open pipe1");
if((fds[1]=open("pipe2", O_RDWR|O_NONBLOCK))<0)
err_quit("Open pipe2");
FD_ZERO(&watchset); //清除watchset集合
FD_SET(fds[0],&watchset); //把串口0的描述符com[COM0].fd添加到watchset中
FD_SET(fds[1],&watchset);
maxfd=fds[0]>fds[1] ? fds[0]:fds[1];
while(FD_ISSET(fds[0],&watchset)||FD_ISSET(fds[1],&watchset)){
inset=watchset;
if(select(maxfd+1,&inset,NULL,NULL,NULL)<0)
err_quit("select");
for(i=0;i<2;++i){
if(FD_ISSET(fds[i],&inset)){
rc=read(fds[i],buf,BUFSZ-1); //接收数据
// printf("/n接收字符数:%d/n",rc);
if(rc>0){
buf[rc]=0;
printf("read:%s",buf);
}
else if(rc==0){
close(fds[i]);
FD_CLR(fds[i],&watchset);
}
else
err_quit("read");
}
}
}
exit(EXIT_SUCCESS);
}
void err_quit(char *msg)
{
perror(msg);//#define perror(s) printf("%s: no files!/n", (s))
exit(EXIT_FAILURE);
}*/
/*读写锁设置:进程1设置读锁时,进程2可以设置读锁不能设置写锁
进程1设置写锁时,进程2不能设置读锁也不能设置写锁
*/
/*
void setlock( int fd , int type );
int main( int argc , char *argv [ ] ) {
int fd ;
fd = open ( argv[1] , O_RDWR |O_CREAT , 0666 ) ;
if ( fd < 0 ) {
perror( " open " ) ;
exit ( EXIT_FAILURE ) ;
}
setlock ( fd , F_RDLCK );
printf ( " PID %d read locked %s/n " , getpid(),argv[1]);
getchar();
setlock ( fd , F_UNLCK );
printf ( " PID %d unlocked %s/n " , getpid(),argv[1]);
getchar();
setlock ( fd , F_WRLCK );
printf ( " PID %d write locked %s/n " , getpid(),argv[1]);
getchar();
close(fd);
exit(EXIT_SUCCESS);
}
void setlock(int fd,int type){
struct flock lock;
char msg[80];
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 1;
while(1){
lock.l_type = type;
if((fcntl(fd,F_SETLK,&lock)) == 0 )//操作成功
return ;
fcntl(fd,F_GETLK,&lock);
if(lock.l_type != F_UNLCK){
switch(lock.l_type){
case F_RDLCK:
sprintf(msg,"read lock already set by %d/n",lock.l_pid);
break;
case F_WRLCK :
sprintf(msg,"write lock already set by %d/n",lock.l_pid);
break;
}
puts(msg);
getchar();
}
}
}*/
/*文件描述符的复制*/
/*void print_line(int n);
int main(int argc , char *argv []){
int fd ;
print_line( 1 );
print_line( 2 );
print_line( 3 );
if ( ( fd = open ("junk.out",O_WRONLY | O_CREAT , 0666 ) ) < 0 ){
perror("open");
exit ( EXIT_FAILURE ) ;
}
if ( (dup2(fd,STDOUT_FILENO)) < 0 ){
perror("dup2");
exit ( EXIT_FAILURE ) ;
}
//下面的输出写入到文件中
print_line( 4 );
print_line( 5 );
print_line( 6 );
close(fd);
close(STDOUT_FILENO);
exit(EXIT_SUCCESS);
}
void print_line(int n){
char buf[80];
snprintf(buf,sizeof(buf),"Line #%d/n",n);
write(STDOUT_FILENO,buf,strlen(buf));
}*/
/*******************************************************/
* *
* c语言标准I/O库 stdio.h *
* 下面函数默认都为该头文件声明的函数 *
/*******************************************************/
/*标准文件函数*/
/*
打开关闭文件函数
FILE *open(const char *path, const char *mode);
功能:以模式mode打开名为path的文件。
参数:*path IN 带路径的文件名
*mode IN 文件打开模式
返回:指向打开文件的指针,打开正确。
指向NULL, 打开失败。
说明:文件打开模式的有效取值
FILE *fdopen(int fildes, const char *mode);
功能:关联文件指针和文件描述符。
参数:fildes IN 文件描述符
*mode IN 文件打开模式
返回:指向打开文件的指针,打开正确。
指向NULL, 打开失败。
说明:文件打开模式的有效取值
FILE *freopen(const char *path, const char *mode, FILE *stream);
功能:以模式mode打开名为path的文件,并且将该文件和stream指向的文件关联。
参数:*path IN 带路径的文件名
*mode IN 文件打开模式
*stream IN 关联文件指针
返回:指向打开文件的指针,打开正确。
指向NULL, 打开失败。
说明:文件打开模式的有效取值
int fclose(FILE *stream);
功能:关闭stream指向的文件。
参数:*stream IN 关联文件指针
返回:0, 关闭成功。
EOF,关闭失败,并设置errno。
说明:
*/
/*
读写文件函数
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从stream指向的文件中读取nmemb*size长度的数据存入ptr指向的空间中。
参数:ptr 指向保存数据的缓冲空间
size 记录长度
nmemb 记录数
stream 指向读取的文件
返回:实际读取的记录数
< 0 出错
说明:
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:写ptr指向的空间中nmemb*size长度的数据到stream指向的文件中。
参数:ptr 指向保存数据的缓冲空间
size 记录长度
nmemb 记录数
stream 指向读取的文件
返回:实际写入的记录数
< 0 出错
说明:
*/
/*
文件状态的获取
int feof(FILE *stream);
功能:
参数:stream IN 文件指针
返回:0 没有遇到EOF
非0 遇到EOF
说明:检测EOF的可靠方法。
int c;
while((c = fgetc(stream)) != EOF ){}
int ferror(FILE *stream);
功能:如果在stream流上设置了errno变量,返回非0值。
void clearerr(FILE *stream);
功能:清楚stream流上的EOF标志和出错标志。
int fileno(FILE *stream);
功能:返回对应的文件描述符。
*/
/*格式化输出函数
#include <stdio.h>
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
#include <stdarg.h>
int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
*/
/*格式化输入函数
#include <stdio.h>
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
#include <stdarg.h>
int vscanf(const char *format, va_list ap);
int vfscanf(FILE *stream, const char *format, va_list ap);
int vsscanf(const char *str, const char *format, va_list ap);
*/
/*字符输入输出
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar(void);
int ungetc(int c, FILE *stream);
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
*/
/*行输入输出函数
char *fgets(char *s, int size, FILE *stream);
char *gets(char *s);
int fputs(const char *s, FILE *stream);
int puts(const char *s);
*/
/*文件定位函数
int fseek(FILE *stream, long offset, int whence);
功能:移动文件位置指针;
参数:stream,文件指针 IN
offset 指针偏移 IN
whence 指针移动方式 IN
返回:指针移动后位置
说明:指针移动方式的设置
SEEK_SET 设置文件指针到文件的offset字节处
SEEK_CUR 设置文件指针到当前位置偏移offset字节处
SEEK_END 设置文件指针位置从文件尾往回offset字节处
long ftell(FILE *stream);
功能:返回当前文件位置指针;
int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, fpos_t *pos);
void rewind(FILE *stream);
功能:移动文件位置指针到文件起始位置;
*/
/*缓冲区控制函数
int fflush(FILE *stream);
功能:将缓冲区中未写入设备的数据写入stream流上;
int setbuf(FILE *stream, char *buf);
int setbuffer(FILE *stream, char *buf, size_t size);
int setlinebuf(FILE *stream);
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
/*文件删除和改名
int remove(const char *pathname);
功能:删除文件;
参数:
返回:0, 成功
-1,失败
说明:
int rename(const char *oldpath, const char *newpath);
*/
/*临时文件
#include <stdio.h>
FILE *tmpfile(void);
char *tmpnam(char *s);
#include <unistd.h>
int mkstemp(char *template);
*/
/*目录操作*/
/*p191-195*/
/******************************************进程********************************************************/
/*进程属性函数
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
功能:获取进程ID
pid_t getppid(void);
功能:获取进程父ID
uid_t getuid(void);
功能:获取真实用户ID
uid_t geteuid(void);
功能:获取有效用户ID
gid_t getgid(void);
功能:获取真实用户组
gid_t getegid(void);
功能:获取有效用户组
*/
/*
* pripds.c - Print PID and PPID
*/
/*
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
printf("PID = %d/n", getpid());
printf("PPID = %d/n", getppid());
exit(EXIT_SUCCESS);
}
*/
/*
* ids.c - Print UIDs and GIDs
*/
/*
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
printf("Real user ID: %d/n", getuid());
printf("Effective user ID: %d/n", geteuid());
printf("Real group ID: %d/n", getgid());
printf("Effective group ID: %d/n", getegid());
exit(EXIT_SUCCESS);
}
*/
/*用户和用户组信息
#include <unistd.h>
char *getlogin(void);
功能:获取登陆用户名
#include <pwd.h>
struct passwd *getpwnam(const char *name);
功能:获取用户名在/etc/passwd文件中的条目
*/
/*
* getname.c - Get login names
*/
/*
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
int main(void)
{
char *login;
struct passwd *pentry;
// Get the login name
if((login = getlogin()) == NULL) { // oops cuserid()???
perror("getlogin");
exit(EXIT_FAILURE);
}
// Get the password entry for login
if((pentry = getpwnam(login)) == NULL) {
perror("getpwnam");
exit(EXIT_FAILURE);
}
// Display the password entry
printf("user name: %s/n", pentry->pw_name);
printf("UID : %d/n", pentry->pw_uid);
printf("GID : %d/n", pentry->pw_gid);
printf("gecos : %s/n", pentry->pw_gecos);
printf("home dir : %s/n", pentry->pw_dir);
printf("shell : %s/n", pentry->pw_shell);
exit(EXIT_SUCCESS);
}*/
/*获取进程资源情况和时间情况
#include <sys/times.h>
#include <sys/resource.h>
#include <unistd.h>
int getrusage(int who, struct rusage *usage);
功能:获取who指定进程的资源
参数:who IN 进程
usage OUT 待填充的资源结构
返回:0,执行成功
-1,执行失败
说明:RUSAGE_SELF 调用进程
RUSAGE_CHILDREN 调用进程子进程
struct rusage{
/* Total amount of user time used. */
struct timeval ru_utime;
/* Total amount of system time used. */
struct timeval ru_stime;
/* Maximum resident set size (in kilobytes). */
long int ru_maxrss;
/* Amount of sharing of text segment memory
with other processes (kilobyte-seconds). */
long int ru_ixrss;
/* Amount of data segment memory used (kilobyte-seconds). */
long int ru_idrss;
/* Amount of stack memory used (kilobyte-seconds). */
long int ru_isrss;
/* Number of soft page faults (i.e. those serviced by reclaiming
a page from the list of pages awaiting reallocation. */
long int ru_minflt;
/* Number of hard page faults (i.e. those that required I/O). */
long int ru_majflt;
/* Number of times a process was swapped out of physical memory. */
long int ru_nswap;
/* Number of input operations via the file system. Note: This
and `ru_oublock' do not include operations with the cache. */
long int ru_inblock;
/* Number of output operations via the file system. */
long int ru_oublock;
/* Number of IPC messages sent. */
long int ru_msgsnd;
/* Number of IPC messages received. */
long int ru_msgrcv;
/* Number of signals delivered. */
long int ru_nsignals;
/* Number of voluntary context switches, i.e. because the process
gave up the process before it had to (usually to wait for some
resource to be available). */
long int ru_nvcsw;
/* Number of involuntary context switches, i.e. a higher priority process
became runnable or the current process used up its time slice. */
long int ru_nivcsw;
};
#include <sys/times.h>
clock_t times(struct tms *buf);
功能:获取系统运行后的时钟计数(墙上时钟)。
参数:*buf IN tms结构缓冲
返回:时钟tick数
说明:struct tms{
clock_t tms_utime;
clock_t tms_stime;
clock_t tms_cutime;
clock_t tms_cstime;
};
进程的三种时间:
墙上时间即流逝的时间(wall clock time)
用户CPU时间(user cpu time)
系统CPU时间(system cpu time)
*/
/*
* resusg1.c - Get process times
*/
/*
#include <stdio.h>
#include <stdlib.h>
#include <sys/times.h>
#include <time.h>
#include <unistd.h>
void doit(char *, clock_t);
int main(void)
{
clock_t start, end;
struct tms t_start, t_end;
start = times(&t_start);
// Redirect output to prevent screen clutter
system("grep the /usr/doc/*/* > /dev/null 2> /dev/null");
end = times(&t_end);
doit("elapsed", end - start);
puts("parent times");
doit("/tuser CPU", t_end.tms_utime);
doit("/tsys CPU", t_end.tms_stime);
puts("child times");
doit("/tuser CPU", t_end.tms_cutime);
doit("/tsys CPU", t_end.tms_cstime);
exit(EXIT_SUCCESS);
}
void doit(char *str, clock_t time)
{
// Get clock ticks/second
long tps = sysconf(_SC_CLK_TCK);
printf("%s: %6.2f secs/n", str, (float)time/tps);
}*/
/*进程创建
#include <stdlib.h>
int system(const char *string);
功能:创建进程
参数:
返回:
说明:
#include <unistd.h>
pid_t fork(void);
功能:创建进程
参数:
返回:-1 执行失败
0 子进程
!0 父进程
说明:
#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, char *const envp[]);
int execv(const char *path, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
int execvp(const char *file, char *const argv[]);
功能:执行进程,代替原有进程映像
参数:path IN 待执行的二进制文件或脚本的完整路径
arg IN 传递给程序的完整参数列表,一般为执行程序名字
file IN 文件名不包含路径,模仿SHELL的行为搜索二进制文件。
返回:
说明:并不产生新的进程,代替原有进程。
#include <stdio.h>
FILE *popen(const char *command, const char *type);
功能:
参数:command IN 待执行的二进制文件或脚本的完整路径
type IN r 读取管道的stdout
w 写入stdin
返回:文件流
说明:并不产生新的进程,代替原有进程。
int pclose(FILE *stream);
*/
/*环境变量
#inlcude <stdlib.h>
int putenv(const char *string);
功能:设置环境变量
char *getenv(const char *name);
功能:获取环境变量
char envval[] =
*/
/*控制进程
等待进程
#include <sys/wait.h>
#include <sys/types.h>
pid_t wait(int *status);
功能:
参数:status IN 子进程结束状态值
返回:
说明:
pid_t waitpid(pid_t pid, int *status, int options);
功能:等待指定子进程退出,并保存退出状态。
参数:pid IN 子进程进程号
status IN 子进程结束状态值
options IN WNOHANG(非阻塞状态)立即返回
返回:如果执行成功则返回子进程识别码(PID).
如果有错误发生则返回,返回值-1.失败原因存于 errno 中。
WNOHANG状态下,如果子进程存活,则返回0。如果子进程已死亡,返回子进程号。
说明:暂时停止目前进程的执行,直到有信号来到或子进程结束.
pid<-1 等待进程组识别码为 pid 绝对值的任何子进程。
pid=-1 等待任何子进程,相当于 wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为 pid 的子进程。
status
WIFEXITED(status)如果子进程正常结束则为非 0 值。
WEXITSTATUS(status)取得子进程 exit()返回的结束代码,一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真
WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为真。一般只有使用 WUNTRACED 时才会有此情况。
WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用 WIFSTOPPED 来判断后才使用此宏。
options
WNOHANG 如果没有任何已经结束的子进程则马上返回, 不予以等待。
WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
*/
/*终止进程
#include <signal.h>
#include <sys/types.h>
int kill(pid_t pid,int sig);
功能:
参数:pid IN 待杀死的进程号
sig IN 要发送的信号,用于杀死进程的信号:SIGKILL、SIGTERM、SIGQUIT。
返回:0 执行成功;
-1 执行失败,设置errno。
说明:用来终止进程或进程组,也可以向进程发送任何信息。
*/
/*信号
发送信号使用KILL,进程能够响应除了SIGSTOP和SIGKILL之外的所有其他信号。
/*
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
功能:设置一个定时器,在定时时间到后发送SIGALRM信号。
参数:seconds IN 定时的S数.
返回:0 没有设置其它超时
n 前面安排的超时中保留的S数
说明:
#include <unistd.h>
int pause(void)
功能:挂起调用它的进程直至有信号到达。
参数:
返回:-1 设置errno为EINTR。
说明:用来终止进程或进程组,也可以向进程发送任何信息。
*/
/*信号处理函数
int sigemptyset(sigset_t *set);
功能:初始化信号集合,不包含任何信号。
参数:set OUT 空信号集合
返回:0 执行成功;
-1 出错。
说明:
int sigfillset(sigset_t *set);
功能:初始化信号集合,包含所有信号。
参数:set OUT 所有信号集合
返回:0 执行成功;
-1 出错。
int sigaddset(sigset_t *set, int signum);
功能:把信号signum添加到信号集合中。
参数:set OUT 信号集合
signum IN 待添加的信号
返回:0 执行成功;
-1 出错。
说明:
int sigdelset(sigset_t *set, int signum);
功能:把信号signum从信号集合中删除。
参数:set OUT 信号集合
signum IN 待删除的信号
返回:0 执行成功;
-1 出错。
说明:
int sigismember(const sigset_t *set, int signum);
功能:判断signum是否在信号集合中。
参数:set OUT 信号集合
signum IN 待测试的信号
返回:1 信号在集合中;
0 信号不在集合中。
说明:
*/
/*登记信号处理器
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
功能:根据how设置或检查当前的信号掩码。
参数:how
set OUT 信号集合
oldset IN
返回:0 执行成功;
-1 执行失败。
说明:how
SIG_BLOCK set包含要阻塞的信号;
SIG_UNBLOCK set包含要解除阻塞的信号;
SIG_SETMASK set包含新的信号掩码
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
功能:为signum指定的信号设置信号处理器。
参数:signum IN 信号
act OUT 信号集合
oldact IN
返回:0 执行成功;
-1 执行失败。
说明:struct sigaction{
void (*sa_hundler)(int);/*信号处理函数*/
sigset_t sa_mask;/*执行处理期间阻塞的其他信号集合*/
int sa_flags;/*修正处理函数行为*/
void (*sa_restorer)(void);/*不使用*/
}
信号处理函数:可以是自定义处理函数,也可以是SIG_DFL默认处理函数,SIG_IGN忽略这个信号
修正处理函数:SA_NOCLDSTOP 进程忽略子进程产生的任何SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOUT信号;
SA_ONESHOT/SA_RESETHAND 登记的自定义信号处理函数只执行一次。在执行完毕后,恢复信号的默认动作。
SA_RESTART 让可重启的系统调用起作用。
SA_NOMASK/SA_NODEFER 不避免在信号自己的处理器中接收信号本身。
*/
/*检测未决信号
#include <signal.h>
int sigpending(sigset_t *set);
功能:检查未决信号,并且将未决信号加入到集合中
参数:set IN 未决信号集合
返回:0 执行成功;
-1 执行失败。
说明:
*/
*/
/*进程调度
+++++++++++++++++++++++++++++++
*/
/******************************************线程********************************************************/
1. 启动线程功能的两种方法:
1) 编译阶段,测试宏 #ifdef _POSIX_THREADS。
2) 运行阶段,使用_SC_THREADS常数调用sysconf函数。
2. 相关函数
1) 头文件:#include <pthread.h>
2) int pthread_equal(pthread_t tid1, pthread_t tid2);/*相等返回非0,否则返回0*/
3) pthread_t pthread_self(void);/*返回调用线程的线程ID*/
4) int pthread_detach(pthread_t tid);/*将线程分离,成功返回0,失败返回错误编号*/
5) 清理函数
6) 退出函数
7) 获取线程返回状态
8) 线程取消函数
3. 使用多线程时,编译的时候要链接多线程库,使用gcc –lthread *c
库名:pthread(libpthread.o)
头文件:<pthread.h>
int pthread_creat(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),void *arg);
功能:创建一个新的线程
参数:thread OUT 返回新线程的标识符;
attr IN 新线程的属性,通过pthread_attr_init设置;
start_routine IN 指向待执行函数
arg IN 向参数3函数传递参数
返回:0 执行成功;
!0 执行失败,返回出错代码。
说明:
int pthread_join(pthread_t th, void **thread_return);
功能:挂起调用者,等待th指定线程返回。
参数:th IN 指定等待线程;
thread_return OUT 保存指定线程的返回值。
返回:
说明:
int pthread_detach(pthread_t th);
void pthread_exit(void *retval);
功能:终止调用者线程,并且将retval指向数据返回。
参数:retval OUT 线程终止时返回的数据指针;
返回:
说明:
/******************************************进程通讯****************************************************/
/*无名管道:只能用于fork之间进程的操作。
命令使用:
cut -f1 -d: </etc/group | sort
/etc/group作为cut命令的输入,使用重定向技术;
cut命令的输出,作为sort的输入,使用管道技术;
相关函数:
头文件:#include <unistd.h>
int pipe(int filedes[2]);
功能:创建管道;
参数:filedes[0] OUT 从管道读数据描述符;
filedes[1] OUT 向管道写数据描述符;
返回:0,执行成功;
-1,执行失败;设置errno。
说明:filedes[0]用O_RDONLY方式打开;
filedes[1]用O_WRONLY方式打开;
使用结束时,要确保两个文件描述符全部关闭。使用close();
使用时,一个进程读管道数据,另一个进程写管道数据;
当向管道写数据时,需要关闭读文件描述符。同时,对应的读管道数据的进程要
关闭写数据文件描述符。
头文件:#include <stdio.h>
FILE *popen(const char *command, const char *mode);
功能:创建管道,然后fork一个子进程,接着执行一个exec调用,调用/bin/sh -c执行保存在command
中的命令字符串。
参数:command IN 指向命令字符串的指针;
mode IN r(or)w;
返回:用于读写的文件流,执行成功;
NULL,执行失败;设置errno。
说明:mode = r,popen返回的FILE流指针用于读command的标准输出;
mode = w,popen返回的FILE流指针用于向command的标准输入写数据。
int pclose(FILE *stream);
功能:关闭I/O流。
参数:stream IN 指定的文件流;
返回:退出状态,执行成功;
-1,执行失败。
说明:
*/
/*有名管道(FIFO):能用于无关进程之间的操作。
命令使用:
mkfifo [option] name
mkfifo -m 600 fifo1
创建一个名为fifo的管道;
相关函数:
头文件:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
功能:用mode指定的权限位创建一个名为pathname的FIFO。
参数:pathname IN FIFO名字
mode IN FIFO的权限
返回:0,执行成功;
-1,执行失败;
说明:mode中的值会被进程中的umask修改。
修改规则为mode&~umask
可能返回的错误值:EACCESS、EECIST、ENAMETOOLONG、ENOENT、ENOSPC、ENOTDIR、EROFS。
打开、读写、删除、读取、写入操作等同与对文件操作;
使用函数open、close、unlink、read、write。
注意:FIFO两端都必须在使用之前打开;
打开时通过使用O_NONBLOCK可以使读写操作立即返回。
相关问题:
如何获取和设置进程的umask。
答案:通过umask函数。具体参照本文件中umask函数的说明。
/*********************************IPC*******************************/
在创建一个system v ipc对象的时候,进程的umask不会修改对象的访问权限;
如果没有设置访问权限,模式为0,所有人都没有对它的读写权。
/*共享内存
命令:ipcs -m 打印共享内存;
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
函数:
int shmget(key_t key, int size, int flags);
功能:创建一个新的共享内存段,或者返回key指定的共享内存段的标示。
参数:key IN 共享段关键字.
size IN 共享段的大小.
flags IN 创建标志.
返回:段标识符,执行成功
-1,执行失败;
说明:key:IPC_PRIVATE,系统随机指定一个键值;
也可以有ftok()函数生成;
也可以自己在头文件中定义该键值。
size:创建共享段的大小,受处理器本身页大小的限制。
INTEL 4KB,ALPHA 8KB。
flag:IPC_CREAT、IPC_EXCL和一组权限位(模式)按位”或“的结果。
IPC_EXCL:当段已经存在时,返回-1,而不是段标示符;
IPC_CREAT:如果没有和KEY关联的段就创建一个新段。
char *shmat(int shmid, char *shmaddr, int flags);
功能:附加共享内存段到调用进程地址空间中。
参数:shmid IN 共享段标识符.
shmaddr IN 共享段的进程映像地址,一般设置为0由进程自动分配。
flags IN 读写标志.SHM_RDONLY,该段只读,默认可读写。
返回:附加段地址,执行成功
-1,执行失败;
说明:
int shmds(char *shmaddr);
功能:将进程地址空间中的附加内存共享段分离出去。
参数:
shmaddr IN shmat的返回值。
返回:0,执行成功
-1,执行失败;
说明:
*/
/*消息队列
命令:ipcs -q
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
函数:
int msgget(key_t key, int flags);
功能:返回新的或已有队列的队列ID。
参数:key IN 消息队列关键字.
flags IN 创建标志。
返回:0,执行成功
-1,执行失败;
说明:key:IPC_PRIVATE,系统随机指定一个键值;
也可以自己在头文件中定义该键值。
flag:IPC_CREAT和一组权限位(模式)按位”或“的结果。
IPC_CREAT:如果没有和KEY关联的段就创建一个新段。
int msgsnd(int msqid, const void *ptr, size_t nbytes, int flags);
功能:向队列中写入消息。
参数:msqid IN 消息队列id号。
ptr IN 指向msgbuf结构的指针。
nbytes IN 添加消息的字节数
flags IN 创建标志。
返回:0,执行成功
-1,执行失败;设置错误变量为EAGAIN、EACCES、EFAULT、EIDRM、EINTR、EINVAL、ENOMEM。
说明:struct msgbuf{
long mtype;/*任何大于0的值*/
char mtext[1];/*长度为nbytes-末尾的null字符*/
};
消息不应该以null结尾;
flag:0, 阻塞方式;
IPC_NOWAIT, 非阻塞方式;
int msgrcv(int msqid, void *ptr, size_t nbytes, long type, int flags);
功能:删除从队列返回的消息。
参数:msqid IN 消息队列id号。
ptr IN 指向msgbuf结构的指针。
nbytes IN 读取消息的字节数.
type IN 决定返回哪个消息。
flags IN 创建标志。
返回:0,执行成功
-1,执行失败;设置错误变量为EAGAIN、EACCES、EFAULT、EIDRM、EINTR、EINVAL、ENOMEM。
说明:type:0,返回队列中的第一条消息;
大于0,返回msg_type等于type的第一条消息;
小于0,返回msg_type为小于等于type绝对值的最小值的第一条消息;
flag:MSG_NOERROR, 返回的消息比nbytes字节多,截断到nbytes字节;
否则返回-1,设置errno值为E2BIG,消息仍旧在队列中。
IPC_NOWAIT, 没有指定类型的消息,立即返回,设置ENOMSG;
否则阻塞。
int msgctl(int msgid, int cmd, struct msgid_ds *buf);
功能:根据cmd不同值进行不同的操作。
参数:msqid IN 消息队列id号。
cmd IN 。
buf OUT 获取队列的msgid_ds结构。
返回:0,执行成功
-1,执行失败;设置错误变量为EAGAIN、EACCES、EFAULT、EIDRM、EINTR、EINVAL、ENOMEM。
说明:cmd:IPC_RMID,删除队列msgid;
IPC_STAT,用队列的msgid_ds结构填充buf,并可以查看队列的内容而不会删除任何消息。
IPC_SET,可以改变队列的UID、GID、访问模式和队列的最大字节数。
*/
/*信号灯
命令:ipcs -s
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
函数:
int semget(key_t key, int nsems, int flags);
功能:同另外两种IPC对象。
int semop(int semid, struct sembuf *semops, unsigned nops);
功能:
参数:
返回:
说明:struct sembuf{
short sem_num;
short sem_op;
short sem_flg;
}
sem_num是信号灯的编号,其值从0到nsems-1;
sem_op是执行的操作;为正,信号灯控制的资源被释放,而且信号灯的值增加;
为负,调用进程表示它将等待直到受控资源被释放,此时信号灯的值减小而资源被调用进程加锁;
为0, 调用进程阻塞直到信号灯变为0;如果信号灯已经是0,调用立即返回。
sem_flg调整semop的行为;
int semctl(int semid, int semnum, int cmd, union semun arg);
功能:
参数:
返回:
说明:
*/
/********************************************GDB********************************************************/
/********************************************内存管理*******************************************************/
/*C内存管理
命令:
头文件:
#include <stdlib.h>
函数:
/****堆上操作函数*****/
void *malloc(size_t size);
功能:分配size字节的未初始化内存块,返回指向该内存块的指针。
参数:size IN 内存字节数
返回:指向分配内存块的指针,执行成功;
NULL,分配失败;
说明:
实例:
char *pmem;
if((pmem = malloc(sizeof(char)*100)) == NULL)
{
/*错误处理*/
}
void *calloc(size_t nmemb, size_t size);
功能:分配size*nmemb字节的初始化为0的内存块,返回指向该内存块的指针。
参数:nmemb IN 内存单元数
size IN 单元字节数
返回:指向分配内存块的指针,执行成功;
NULL,分配失败;
说明:
实例:
void *realloc(void *ptr, size_t size);
功能:改变已分配内存块的大小。
参数:ptr IN 指向由calloc或malloc分配的内存;
size IN 重新分配的字节数;
返回:指向调整后内存块的指针,执行成功;
NULL,分配失败;
说明:首先在原内存块进行增加或减小操作,如果不能原地操作则将原来的数据调整到新的内存块;
不对增加的内存块做初始化;
如果不能扩大内存块,返回NULL,保持原来的数据不动;
第一个参数设置为NULL,同malloc函数作用;
第二个参数设置为0,释放原来的内存块;
实例:
void free(void *ptr);
功能:释放ptr指向的内存;
参数:
返回:
说明:
实例:
/****栈上操作函数*****/
void *alloca(size_t size);
功能:分配一块未经初始化的内存;
参数:
返回:
说明:该内存从栈上获取;
函数调用者退出时,分配内存自动释放;
实例:
*/
/*内存映像文件
命令:
头文件:
#include <unistd.h>
#include <sys/mman.h>
函数:
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
功能:把fd指定的磁盘文件从offset偏移处length长度的内容映射到start指定的内存处;
参数:start IN 指向映射内存地址
length IN 文件被映射的大小
prot IN 保护模式
flags IN 映像的属性
offset IN 文件开始映像的偏移
返回:指向映射内存区地址,执行成功;
-1,执行失败,设置errno变量;
说明:prot,
PORT_NONE 不允许访问;
PORT_READ 映像内存区可读;
PORT_WRITE 映像内存区可写;
PORT_EXEC 映像内存区可执行;
flags,
MAP_FIXED 如果start无效或者正在使用则失效;
MAP_PRIVATE 对映像内存的写入操作是进程私有的;
MAP_SHARD 对映像内存的写入也被复制到文件;
MAP_ANON 创建匿名映像,忽略fd;
MAP_DENYWRITE 不允许正常的写文件;
MAP_GROWSDOWN 映像内存区是向下增长的;
MAP_LOCKED 把页面锁定在内存中;
映像内存区必须用MAP_PRIVATE和MAP_SHARD之一,其余可选;
int munmap(void *start, size_t length);
功能:解除内存映像并且把内存返回给操作系统;
参数:start IN 指向待解除映像的内存地址
length IN 待解除映像的内存大小
返回:0,执行成功;
-1,执行失败,设置errno变量;
说明:
int msync(const void *start, size_t length, int flags);
功能:把被映像的文件写入磁盘;
参数:start IN 映像的内存地址
length IN 映像的内存大小
flag IN 写入标志:MS_ASYNC()/MS_SYNC()/MS_INVALIDATE()
返回:0,执行成功;
-1,执行失败,设置errno变量;
说明:
int mprotect(const void *start, size_t length, int prot);
功能:修改内存区的保护模式;
参数:start IN 映像的内存地址
length IN 映像的内存大小
prot IN 新的模式
返回:0,执行成功;
-1,执行失败,设置errno变量;
int mlock(const void *start, size_t len);
int munlock(void *start,size_t len);
int mlockall(int flags);
int munlockall(void);
功能:锁定内存;
void *mremap(void *old_addr, size_t old_len, size_t new_len, unsigned long flags);
功能:调整映像内存区的大小;
返回:调整后的地址,执行成功;
NULL,执行失败
说明:flags = MREMAP_MAYMOVE允许改动地址,否则不允许改动地址;
*/
/*常见内存问题
*/
/*********************************************网络编程*****************************************************/
/*分配空间和初始化
int socket(int domain, int type, int protocol);
功能:建立套接口描述字;
参数:domain, 域类型 IN
type, 套接口类型 IN
protocol, 协议号 IN
返回:套接口描述字
说明:域类型取值/usr/include/sys/socket.h
............/bits/socket.h
AF_UNIX---UNIX内部协议
AF_INET---ARAP网际协议
AF_ISO----国际标准组织协议
AF_NS-----Xerox网络系统协议
套接口类型取值
SOCK_STREAM-------
SOCK_DGRAM--------
SOCK_RAW----------
SOCK_SEQPACKET----
SOCK_RDM----------
int bind(int socket, struct sockaddr *my_addr, int my_addr_legth);
功能:连接一个进程和一个套接口;
参数:socket, 套接口描述字 IN
my_addr, IN
my_addr_legth, IN
返回:套接口描述字
说明:struct sockaddr{
unsigned short sa_family;
char sa_data[14];
};
struct sockaddr_in sin;
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(port);
bind(sock_descriptor, (struct sockaddr *)&sin, sizeof(sin));
*/
/*完成连接
服务器端:
int listen(int socket, int input_queue_size);
功能:;
参数:, 套接口描述字 IN
, IN
, IN
返回:
说明:
int accept(int socket, struct sockaddr *my_addr, int *my_addr_length);
功能:;
参数:, 套接口描述字 IN
, IN
, IN/OUT
返回:
说明:
客户端:
int connect(int socket, struct sockaddr *server_address, int server_address_length);
功能:;
参数:, 套接口描述字 IN
, IN
, IN/OUT
返回:
说明:
*/
/*传输数据
int recv(int socket, void *buf, int buf_len, unsigned int flags);
int send(int socket, const void * message_data, int message_data_length, unsigned int flags);
*/
/*关闭
int close(int socket);
*/
/********************************************定时器***************************************************/
#include <sys/time.h>
int getitimer(int which, struct itimerval *value);
功能:获取定时器的当前值
参数:which IN 返回信号和计时类型;
value OUT 当前计数值
返回:成功执行时,返回0。
失败返回-1,errno被设为以下的某个值
EFAULT:value 或ovalue是不有效的指针
EINVAL:其值不是ITIMER_REAL,ITIMER_VIRTUAL 或 ITIMER_PROF之一
说明:
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);
功能:获取定时器的当前值
参数:which IN 返回信号和计时类型;
value OUT 当前计数值
ovalue OUT 返回原有计数值
返回:成功执行时,返回0。
失败返回-1,errno被设为以下的某个值
EFAULT:value 或ovalue是不有效的指针
EINVAL:其值不是ITIMER_REAL,ITIMER_VIRTUAL 或 ITIMER_PROF之一
说明:struct itimerval {
struct timeval it_interval;
struct timeval it_value;
};
struct timeval {
long tv_sec;
long tv_usec;
};
which:间歇计时器类型,有三种选择
ITIMER_REAL //数值为0,以系统真实的时间来计算,发送的信号是SIGALRM。
ITIMER_VIRTUAL //数值为1,以该进程在用户态下花费的时间来计算,发送的信号是SIGVTALRM。
ITIMER_PROF //数值为2, 以该进程在用户态下和内核态下所费的时间来计算,发送的信号是SIGPROF。
/*********************************************终端控制*****************************************************/
/*终端控制
命令:
头文件:
#include <termios.h>
#include <unistd.h>
函数:
int tcgetattr(int fd, struct termios *tp);
功能:
参数:
返回:
说明:
int tcsetattr(int fd, int action, struct termios *tp);
功能:
参数:
返回:
说明:
int cfgetispeed(struct termios *tp)
功能:
参数:
返回:
说明:
int cfsetispeed(struct termios *tp, speed_t speed)
功能:
参数:
返回:
说明:
相关结构:
struct termios
{
tcflag_t c_iflag;
tcflag_t c_oflag;
tcflag_t c_cflag;
tcflag_t c_lflag;
cc_t c_line;
cc_t c_cc[NCCS];
}
*/