sysconf
1、前言
当前计算机都是多核的,linux2.6提供了进程绑定cpu功能,将进程指定到某个core上执行,方便管理进程。linux提供了sysconf系统调用可以获取系统的cpu个数和可用的cpu个数。
2、sysconf 函数
man一下sysconf,解释这个函数用来获取系统执行的配置信息。例如页大小、最大页数、cpu个数、打开句柄的最大个数等等。详细说明可以参考man。
3、测试程序
写一个测试程序,方便日后使用。
#include <stdio.h>
#include <unistd.h>
#define ONE_MB (1024 * 1024)
int main()
{
printf("The number ofprocessors configured is :%ld\n",
sysconf(_SC_NPROCESSORS_CONF));
printf("The number ofprocessors currently online (available) is :%ld\n",
sysconf(_SC_NPROCESSORS_ONLN));
printf("The pagesize: %ld\n", sysconf(_SC_PAGESIZE));
printf ("The numberof pages: %ld\n",sysconf(_SC_PHYS_PAGES));
printf ("The numberof available pages: %ld\n",sysconf(_SC_AVPHYS_PAGES));
printf ("The memorysize: %lld MB\n",
(long long)sysconf(_SC_PAGESIZE)* (long long)sysconf(_SC_PHYS_PAGES)/ ONE_MB );
printf ("The numberof files max opened:: %ld\n",sysconf(_SC_OPEN_MAX));
printf("The number ofticks per second: %ld\n",sysconf(_SC_CLK_TCK));
printf ("The maxlength of host name: %ld\n",sysconf(_SC_HOST_NAME_MAX));
printf ("The maxlength of login name: %ld\n",sysconf(_SC_LOGIN_NAME_MAX));
return 0;
}
我的虚拟机配置了4个核,1G的内存,32位的linux。执行结果如下:
pipe函数
1. 函数说明
pipe(建立管道):1) 头文件 #include<unistd.h>
2) 定义函数: int pipe(int filedes[2]);
3) 函数说明: pipe()会建立管道,并将文件描述词由参数filedes数组返回。
filedes[0]为管道里的读取端
filedes[1]则为管道的写入端。
4) 返回值: 若成功则返回零,否则返回-1,错误原因存于errno中。
错误代码:
EMFILE 进程已用完文件描述词最大量
ENFILE 系统已无文件描述词可用。
EFAULT 参数 filedes 数组地址不合法。
2. 举例
#include <unistd.h>
#include <stdio.h>
int main( void )
{
int filedes[2];
char buf[80];
pid_t pid;
pipe( filedes );
pid=fork();
if (pid > 0)
{
printf( "This is in the father process,here write a string to the pipe.\n" );
char s[] = "Hello world , this is write by pipe.\n";
write( filedes[1], s, sizeof(s) );
close( filedes[0] );
close( filedes[1] );
}
else if(pid == 0)
{
printf( "This is in the child process,here read a string from the pipe.\n" );
read( filedes[0], buf, sizeof(buf) );
printf( "%s\n", buf );
close( filedes[0] );
close( filedes[1] );
}
waitpid( pid, NULL, 0 );
return 0;
}
运行结果:
[root@localhost src]# gcc pipe.c
[root@localhost src]# ./a.out
This is in the child process,here read a string from the pipe.
This is in the father process,here write a string to the pipe.
Hello world , this is write by pipe.
当管道中的数据被读取后,管道为空。一个随后的read()调用将默认的被阻塞,等待某些数据写入。
若需要设置为非阻塞,则可做如下设置:
fcntl(filedes[0], F_SETFL, O_NONBLOCK);
fcntl(filedes[1], F_SETFL, O_NONBLOCK);
全双工管道
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
int main()
{
int fd1[2],fd2[2];
pid_t childpid;
char buf[100];
memset(buf,0,100);
if(pipe(fd1) == -1)
{
perror("pipe() error");
exit(-1);
}
if(pipe(fd2) == -1)
{
perror("pipe() error");
exit(-1);
}
childpid = fork();
if(childpid == 0)
{
printf("Server input a message : ");
gets(buf);
close(fd1[0]);
close(fd2[1]);
write(fd1[1],buf,strlen(buf));
read(fd2[0],buf,100);
printf("Server received message from client:%s\n",buf);
exit(0);
}
if(childpid == -1)
{
perror("fork() error");
exit(-1);
}
close(fd1[1]);
close(fd2[0]);
read(fd1[0],buf,100);
printf("Client receive a message from server: %s\n",buf);
printf("Client input a message : ");
gets(buf);
write(fd2[1],buf,strlen(buf));
waitpid(childpid,NULL,0);
return 0;
}
结果为:
dup和dup2
dup和dup2也是两个非常有用的调用,它们的作用都是用来复制一个文件的描述符。
它们经常用来重定向进程的stdin、stdout和stderr。
这两个函数的 原形如下:
#include <unistd.h>
int dup( int oldfd );
int dup2( int oldfd, int targetfd )
利用函数dup,我们可以复制一个描述符。传给该函数一个既有的描述符,它就会返回一个新的描述符,这个新的描述符是传给它的描述符的拷贝。这意味着,这两个描述符共享同一个数据结构。例如,如果我们对一个文件描述符执行lseek操作,得到的第一个文件的位置和第二个是一样的。
下面是用来说明dup函数使用方法的代码片段:
int fd1, fd2;
...
fd2 = dup( fd1 );
需要注意的是,我们可以在调用fork之前建立一个描述符,这与调用dup建立描述符的效果是一样的,子进程也同样会收到一个复制出来的描述符。dup2函数跟dup函数相似,但dup2函数允许调用者规定一个有效描述符和目标描述符的id。dup2函数成功返回时,目标描述符(dup2函数的第二个参数)将变成源描述符(dup2函数的第一个参数)的复制品,换句话说,两个文件描述符现在都指向同一个文件,并且是函数第一个参数指向的文件。
例子:
int oldfd;
oldfd = open("app_log", (O_RDWR | O_CREATE), 0644 );
dup2( oldfd, 1 );
close( oldfd );
本例中,我们打开了一个新文件,称为“app_log”,并收到一个文件描述符,该描述符叫做oldfd。我们调用dup2函数,参数为oldfd和1,这会导致用我们新打开的文件描述符替换掉由1代表的文件描述符(即stdout,因为标准输出文件的id为1)。任何写到stdout的东西,现在都将改为写入名为“app_log”的文件中。
需要注意的是,dup2函数在复制了oldfd之后,会立即将其关闭,但不会关掉新近打开的文件描述符,因为文件描述符1现在也指向它。
例子:
fd = open("/dev/null", O_RDWR);
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
这样可以抛弃输入,输出。