2018-01-24 15:02:43 yilindai3437 阅读数 64

 今天在学习unix高级编程第三版,测试fig10-23程序的时候,发现并没能出现书上出现的效果,书上代码的效果是通过终端的ctrl+c产生SIGINT号可以一直被阻塞,但是自己测试的时候发现只能对ctrl+c阻塞一次,仔细想了一下,问题应该是出现在signal函数这一块。

 查阅前面10.14节发现书上的signal函数其实都是用fig10-18的程序实现的,我们可以分析一下这个signal函数的属性:由于flag上设置了SA_INTERRUPT位,根据解释可以知道如果在系统调用执行期间超时没有被屏蔽的信号发生了递送的话,这个系统调用是不会被重新执行的,如果没有设置SIGALRM信号,也就不会超时,系统会重新调用。老的不可靠语义的signal函数一般要设置SA_RESETHAND和SA_NODEFER,所以如果触发了信号处理函数,这个信号处理函数只会被执行一次然后信号处理函数指针参数就会被设置成SIG_DFL,下次递送该信号时直接终止。

 fig10_23程序出现的问题就是因为ubantu16:04的系统中的signal实现more是老的语义的signal实现,所以当按下第二次ctrl +c时,由于早已设置成SIG_DFL,所以程序直接终结。解决办法见下图:

 将两个文件联合编译,不用老的不可靠语义的signal函数即可。




   

2017-03-02 14:37:17 a1414345 阅读数 319

练习环境Centos6.5 ,  linux内核版本2.6



p4, 1-3


/*************************************************************************
#	> File Name: 1-3.c
# 
# 
# Created Time: 2017年02月28日 星期二 23时53分36秒
 ************************************************************************/

#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
int main(int argc, char *argv[] )
{
	DIR *dp;
	struct dirent *dirp;

	if(argc != 2)
	{
		printf("usage:ls directory_name");
		return 1;
	}

	if( (dp = opendir(argv[1]))== NULL )
		printf("can't open %s", argv[1]);
	while( (dirp = readdir(dp))!= NULL)
		printf("%s\n",dirp->d_name);
	closedir(dp);

	return 0;
}


p7 1-4

/*************************************************************************
#	> File Name: 1-4.c
# 
# 
# Created Time: 2017年03月01日 星期三 00时08分40秒
 ************************************************************************/

#include<stdio.h>
#include <unistd.h>
#define BUFFSIZE 4096

int main()
{
	int n;
	char buf[BUFFSIZE];

	while((n = read(STDIN_FILENO, buf, BUFFSIZE)) >0 )
	{
		if(write(STDOUT_FILENO,buf, n) != n)
			printf("  write  error \n");
	}
	if(n < 0)
	{
		printf("read error \n");
	}
	return 0;
}


p8 1-5

/*************************************************************************
#	> File Name: 1-5.c
# 
# 
# Created Time: Wed 01 Mar 2017 12:24:11 AM PST
 ************************************************************************/

#include<stdio.h>

int main()
{
	int c;
	while((c = getc(stdin)) != EOF)
		if(putc(c, stdout) == EOF)
			printf("putc error\n");

	if(ferror(stdin))
		printf("input error\n");
	return 0;
}

p9 1-6

/*************************************************************************
#	> File Name: 1-6.c
# 
# 
# Created Time: Wed 01 Mar 2017 12:29:32 AM PST
 ************************************************************************/

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

int main()
{
	printf("hello wrold from process ID %ld \n", (long)getpid());
	return 0;
}


p9 1-7

/*************************************************************************
#	> File Name: 1-7.c
# 
# 
# Created Time: Wed 01 Mar 2017 12:33:40 AM PST
 ************************************************************************/

#include<stdio.h>
#include<sys/wait.h>
#include<unistd.h>
#include<string.h>
#define MAXLINE 4096 

int main()
{
	char buf[MAXLINE];
	pid_t pid;
	int status;
	printf("%%");// printf prompt (printf requires %% to print %)
	while (fgets(buf, MAXLINE, stdin) != NULL)
	{
		if (buf[strlen(buf) - 1] == '\n')
			buf[strlen(buf) - 1] = '\0'; // replace new line witg null

		if ((pid = fork()) < 0)
		{
			printf("fork error\n");
			return 1;
		}
		else if(pid == 0)
		{// child 
			execlp(buf, buf , NULL);
			printf("couldn't execute: %s \n", buf);
			return 2;
		}

		if( (pid = waitpid(pid, &status, 0) < 0))
		{// father

			printf("waitpid error");
			return 3;
		}
		printf("%% ");

	}
	return 0;
}


p12  1-8

/*************************************************************************
#	> File Name: 1-8.c
# 
# 
# Created Time: Wed 01 Mar 2017 01:08:52 AM PST
 ************************************************************************/

#include<stdio.h>
#include <errno.h>
int main(int argc, char* argv[])
{
	fprintf(stderr, "EACCES:%s\n", strerror(EACCES));
	errno = ENOENT;
	perror(argv[0]);
	return 0;
}



p 14 1-9

/*************************************************************************
#	> File Name: 1-9.c
# 
# 
# Created Time: Wed 01 Mar 2017 01:22:31 AM PST
 ************************************************************************/

#include<stdio.h>
#include<unistd.h>
int main()
{
	printf("uid = %d , gid = %d \n", getuid(), getgid());
	return 0;
}


p15 1-10

/*************************************************************************
#	> File Name: 1-10.c
# 
# 
# Created Time: Wed 01 Mar 2017 12:33:40 AM PST
 ************************************************************************/

#include<stdio.h>
#include<sys/wait.h>
#include<unistd.h>
#include<string.h>
#include<signal.h>
#define MAXLINE 4096 

static void  sig_int(int); // our signal-catching function

int main()
{
	char buf[MAXLINE];
	pid_t pid;
	int status;

	if(signal(SIGINT, sig_int) == SIG_ERR)
	{
		printf("signal error");
		return 4;
	}
	printf("%%");// printf prompt (printf requires %% to print %)
	while (fgets(buf, MAXLINE, stdin) != NULL)
	{
		if (buf[strlen(buf) - 1] == '\n')
			buf[strlen(buf) - 1] = '\0'; // replace new line witg null

		if ((pid = fork()) < 0)
		{
			printf("fork error\n");
			return 1;
		}
		else if(pid == 0)
		{// child 
			execlp(buf, buf , NULL);
			printf("couldn't execute: %s \n", buf);
			return 2;
		}

		if( (pid = waitpid(pid, &status, 0) < 0))
		{// father

			printf("waitpid error");
			return 3;
		}
		printf("%% ");

	}
	return 0;
}

void sig_int(int signo)
{
	printf("interrupt\n %%");
}


2017-03-29 17:59:02 banruoju 阅读数 1057

[1]. 106页,myftw函数中,位于起始部位,错误语句“malloc PATH_MAX + 1 bytes ({Flgure 2.16})”,正确的应该是“malloc PATH_MAX + 1 bytes ({Figure 2.15})”,英文原版中也错了。

[2]. 201页,"但新程序从调用进程继承了的下列属性:"这句话翻译得乱七八糟,根据英文原意和上下文语境,应该翻译成"而且新程序还从调用进程继承了以下这些属性:"

[3].  207页,错误语句“at程序做的第一件事就是降低特权,以用户特权运行。它调用setuid函数把有效用户ID设置为实际用户ID”,正确的应该是“at程序做的第一件事就是降低特权,以用户特权运行。它调用seteuid函数把有效用户ID设置为实际用户ID” 。

[4].  207页,错误语句“at命令调用setuid函数把有效用户ID设为root,因为setuid的参数等于保存的设置用户ID”,正确的应该是“at命令调用seteuid函数把有效用户ID设为root,因为seteuid的参数等于保存的设置用户ID”。

[5].  207页,错误语句“修改文件从而记录了将要运行的命令以及它们的运行时间以后,at命令通过调用seteuid,把有效用户ID设置为用户ID”,正确的应该是“修改文件从而记录了将要运行的命令以及它们的运行时间以后,at命令通过调用seteuid,把有效用户ID设置为我们的用户ID”。

[6]. 259页,10.4节"不可靠的信号"第一段中,"同时,进程对信号的控制能力也很差,它能捕捉信号或忽略它"翻译的莫名其妙,应该翻译成"同时,进程对信号的控制能力也很差,它只能捕捉信号或忽略它"

[7]. 328页,main函数中,倒数第2行"printf("can't lock mvtex again:%s\n",strerror(err));"中,"mutex"单词拼写错误

[8]. 333页,第一行中,"因为互斥量必须在锁定以后才能计算条件"翻译欠妥,个人觉得翻译成"因为必须在互斥量锁定以后才能计算条件"更加顺畅

[9]. 346页,最后一段最后一句"但是,即使不使用健壮的互斥量,也可以只检查成功或者失败"翻译的莫名其妙,根据原文意思应该翻译成"而当我们不使用健壮的互斥量时,就可以只检查成功或者失败"

[10]. 358页,12.5小节最后一段中,"如果信号处理程序在线程执行getenv_r时中断了该线程,这时我们已经占有加锁的env_mutex,这样其他线程试图对这个互斥量的加锁就会被阻塞,最终导致线程进入死锁状态"翻译错误,根据原文意思应该翻译为"如果信号处理程序在线程执行getenv_r时中断了该线程,这时我们已经占有加锁的env_mutex,所以下一个试图对这个互斥量的加锁就会被阻塞,最终导致线程进入死锁状态"

[11]. 392页,倒数第二段,"上面提到了两种类型的锁:共享读锁(L_RDLCK)和独占性写锁(L_WRLCK)。"中,两个宏名写错,正确应该是"F_RDLCK"和"F_WRLCK"

[12]. 398页,最后一段中,"un_lock(fd, 0, SEEK_END);",根据前文中对un_lock函数的定义,这里对该函数的调用显然少了最后一个参数,所以正确应该是 "un_lock(fd, 0, SEEK_END,0);". 英文原版和中文翻译中都存在该错误。

[13]. 404页,第二段中,错误语句"POSIX异步I/O是Single UNIX Specification中是可选设施",正确的应该是"POSIX异步I/O是Single UNIX Specification中的可选设施"

[14]. 408页,14.4.2中第一行,错误语句"但是程序员接口有所不同",正确的应该是"但是程序接口有所不同"

[15]. 410页,第一段中,错误语句"信号机构提供了一种以异步形式通知某种事件已发生的方法",正确的应该是"信号提供了一种以异步形式通知某种事件已发生的方法"

[16]. 446页,第一段整个翻译都有问题(ps:特地翻看了一下中文第二版,发现第二版原本这里是翻译的很合理的,显然第三版这里是换了一个菜鸡翻译),合理的翻译应该是"一旦已经用mkfifo或者mkfifoat创建了一个FIFO,就可以用open打开它。其实,一般的文件I/O函数(close、read、write、unlink等)都可用于FIFO"

[17]. 465页,15.9小节最后一段中,错误语句"最后两个实例说明了在多个无关进程之间如何使用共享存储段",正确的应该是"最后两个实例说明了在多个相关进程之间如何使用共享存储段"

[18]. 465页,15.10小节第一段第一句, “POSIX信号量机制是3种IPC机制之一,3种IPC机制源于POSIX.1的 实时扩展”这句翻译太渣了,原文是"The POSIX semaphore mechanism is one of three IPC mechanisms that originated with the real-time extensions to POSIX.1.",对照原意,再联系上下文,应该翻译为"POSIX信号量是3种源自POSIX.1实时扩展的IPC机制中的其中一种"


(如果有发现,持续更新中)

2017-08-27 07:37:59 kingolie 阅读数 663

7.1 在Intel x86系统上,使用Linux,如果执行一个输出“hello world”的程序但不调用exit或return,则程序的返回代码13(用shell检查),解释其原因:

原因:printf的返回值变为main函数的返回值,不同的系统上编译此类程序由不同的终止码。

7.2 图7-3中的printf函数的结果何时才被真正输出?

当程序处于交互运行方式时,标准输出通常处于行缓冲方式,所以当输出换行符时,上次的结果才被真正输出。如果标准输出被定向到一个文件,而标准输出处于全缓冲方式,则当标准I/O清理操作执行时,结果才真正被输出。

7.5 C语言的typedef为处理终止程序定义了一个新的数据类型 Exitfunc,使用该类型修改atexit的原型

typedef void Exitfunc(void);
int     atexit(Exitfunc *func);

7.7 在7.6节结尾处size命令输出结果中,为什么没有给出堆和栈的大小?

只有通过exec函数执行一个程序时,才会分配堆和栈。
2019-05-17 23:25:28 u011285208 阅读数 75

(1)下载源代码,可以去官网下载:http://apuebook.com/code3e.htm

(2)解压缩源代码文件:tar -zxvf src.3e.tar.gz

(3)安装libbsd-devel,否则编译会报错不通过,会提示编译threads文件夹里面的内容时报错:

/tmp/ccvzZHtf.o: In function `thr_fn':
barrier.c:(.text+0x80): undefined reference to `heapsort'
collect2: error: ld returned 1 exit status
make[1]: *** [barrier] Error 1
make[1]: Leaving directory `/home/apue.3e/threads'
make: *** [all] Error 1

我的系统是centos7的,由于centos7系统没有libbsd-devel,网上有很多博客说可以用下面的命令可以安装

sudo yum install libbsd-0.6.0-1.el6.i686.rpm
sudo yum install libbsd-devel-0.6.0-1.el6.i686.rpm

我的系统上反正是不能安装,因此需要自行下载libbsd和libbse-devel,有需要的朋友的可以到我的网盘下载

http://pan.baidu.com/s/1pKK8LQz,也可以在shell中执行以下指令下载:

wget http://elrepo.reloumirrors.net/testing/el6/x86_64/RPMS/libbsd\-0.2.0-4.el6.elrepo.x86_64.rpm

wget http://elrepo.reloumirrors.net/testing/el6/x86_64/RPMS/libbsd-devel-0.2.0-4.el6.elrepo.x86_64.rpm

下载完成后使用RPM安装:

rpm -ivh libbsd-devel-0.2.0-4.el6.elrepo.x86_64.rpm 

rpm -ivh libbsd-0.2.0-4.el6.elrepo.x86_64.rpm 

(4)进入apue.3e文件夹,执行make命令。

 

没有更多推荐了,返回首页