kk Blog —— 通用基础

date [-d @int|str] [+%s|"+%F %T"]

隐藏权限--无法添加用户和组等

执行命令:

1
2
[root@localhost softwaretools]# groupadd mysql
groupadd:无法打开组文件(groupadd: unable to open group file)

此时就奇怪了,当前用的明明是root用户,为什么没有创建组和用户的权限呢。

结论: 1,添加用户需要用到passwd和shadow这两个文件
2,添加组需要用到shadow和gshadow这两个文件

使用 ls -l 命令发现权限正常。

最终发现问题,找到了2个命令(lsattr和chattr),是因为隐藏权限在作怪:
对这2个命令的简单做下说明:
对于某些有特殊要求的档案(如服务器日志)还可以追加隐藏权限的设定。这些隐藏权限包括: Append only (a), compressed ©, no dump (d), immutable (i), data journalling (j),secure deletion (s), no tail-merging (t), undeletable (u), no atime updates (A), synchronous directory updates (D), synchronous updates (S), and top of directory hierarchy (T).
lsattr命令是查看隐藏权限设定情况的,chattr是变更隐藏权限的命令。

首先使用使用lsattr查看了一下这几个文件:

1
2
3
4
5
6
7
8
[root@localhost ~]# lsattr /etc/passwd  
------------- /etc/passwd  
[root@localhost ~]# lsattr /etc/group  
----i-------- /etc/group  
[root@localhost ~]# lsattr /etc/shadow  
------------- /etc/shadow  
[root@localhost ~]# lsattr /etc/gshadow  
----i-------- /etc/gshadow  

可以看到文件被设置的 i 这个隐藏权限,
i:设定文件不能被删除、改名、设定链接关系,同时不能写入或新增内容。
i参数对于文件 系统的安全设置有很大帮助。

既然这样只要把i权限去掉就应该好了。

使用命令chattr命令修改文件隐藏权限,执行如下命令:

1
2
chattr -i /etc/gshadow
chattr -i /etc/group

然后可以正常执行了。

Linux的IPC命令 查看共享内存

http://www.cnblogs.com/cocowool/archive/2012/05/22/2513027.html

进程间通信概述

进程间通信有如下的目的:
1、数据传输,一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M之间;
2、共享数据,多个进程想要操作共享数据,一个进程对数据的修改,其他进程应该立刻看到;
3、通知事件,一个进程需要向另一个或一组进程发送消息,通知它们发生了某件事情;
4、资源共享,多个进程之间共享同样的资源。为了做到这一点,需要内核提供锁和同步机制;
5、进程控制,有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

Linux进程间通信由以下几部分发展而来:
早期UNIX进程间通信:包括管道、FIFO、信号。
基于System V的进程间通信:包括System V消息队列、System V信号灯(Semaphore)、System V共享内存。
基于Socket进程间通信。
基于POSIX进程间通信:包括POSIX消息队列、POSIX信号灯、POSIX共享内存。
Linux中,与IPC相关的命令包括:ipcs、ipcrm(释放IPC)、

IPCS命令是Linux下显示进程间通信设施状态的工具。我们知道,系统进行进程间通信(IPC)的时候,可用的方式包括信号量、共享内存、消息队列、管道、信号(signal)、套接字等形式[2]。使用IPCS可以查看共享内存、信号量、消息队列的状态。

例如在CentOS6.0上执行ipcs

具体的用法总结如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
1、显示所有的IPC设施
# ipcs -a

2、显示所有的消息队列Message Queue
# ipcs -q

3、显示所有的信号量
# ipcs -s

4、显示所有的共享内存
# ipcs -m

5、显示IPC设施的详细信息
# ipcs -q -i id
id 对应shmid、semid、msgid等。-q对应设施的类型(队列),查看信号量详细情况使用-s,查看共享内存使用-m。

6、显示IPC设施的限制大小
# ipcs -m -l
-m对应设施类型,可选参数包括-q、-m、-s。

7、显示IPC设施的权限关系
# ipcs -c
# ipcs -m -c
# ipcs -q -c
# ipcs -s -c

8、显示最近访问过IPC设施的进程ID。
# ipcs -p
# ipcs -m -p
# ipcs -q -p

9、显示IPC设施的最后操作时间
# ipcs -t
# ipcs -q -t
# ipcs -m -t
# ipcs -s -t

10、显示IPC设施的当前状态
# ipcs -u

Linux上的ipcs命令,不支持UNIX上的-b、-o指令,同样UNIX中不支持-l、-u指令,所以在编写跨平台的脚本时,需要注意这个问题。

参考资料:

1、Linux下IPCS的用法详解
2、Linux进程间通信
3、Linux下IPCS的10种用法
4、Linux IPC小结
5、Linux IPC总结

修改共享内存大小

http://blog.csdn.net/l_yangliu/article/details/11193187

1
2
3
4
5
6
7
8
9
10
beijibing@bjb-desktop:/proc/sys/kernel$ cat shmmax 
33554432
beijibing@bjb-desktop:/proc/sys/kernel$ cat shmmni
4096
beijibing@bjb-desktop:/proc/sys/kernel$ cat msgmax
8192
beijibing@bjb-desktop:/proc/sys/kernel$ cat msgmni
622
beijibing@bjb-desktop:/proc/sys/kernel$ cat msgmnb
16384

System V IPC 参数

名字 描述 合理取值
SHMMAX 最大共享内存段尺寸(字节) 最少若干兆(见文本)
SHMMIN 最小共享内存段尺寸(字节) 1
SHMALL 可用共享内存的总数量(字节或者页面) 如果是字节,就和 SHMMAX 一样;如果是页面,ceil(SHMMAX/PAGE_SIZE)
SHMSEG 每进程最大共享内存段数量 只需要 1 个段,不过缺省比这高得多。
SHMMNI 系统范围最大共享内存段数量 类似 SHMSEG 加上用于其他应用的空间
SEMMNI 信号灯标识符的最小数量(也就是说,套) 至少 ceil(max_connections / 16)
SEMMNS 系统范围的最大信号灯数量 ceil(max_connections / 16) * 17 加上用于其他应用的空间
SEMMSL 每套信号灯最小信号灯数量 至少 17
SEMMAP 信号灯映射里的记录数量 参阅文本
SEMVMX 信号灯的最大值 至少 1000 (缺省通常是32767,除非被迫,否则不要修改)

最重要的共享内存参数是 SHMMAX , 以字节记的共享内存段可拥有的最大尺寸。如果你收到来自shmget 的类似Invalid argument 这样的错误信息,那么很有可能是你超过限制了。

有些系统对系统里面共享内存的总数(SHMALL )还有限制。 请注意这个数值必须足够大。(注意:SHMALL 在很多系统上是用页面数,而不是字节数来计算的。)

系统里的最大信号灯数目是由SEMMNS 设置的,因此这个值应该至少和 max_connections 设置一样大,并且每十六个联接还要另外加一个。 参数SEMMNI 决定系统里一次可以存在的信号灯集的数目。 因此这个参数至少应该为 ceil(max_connections % 16) 。降低允许的联接数目是一个临时的绕开失败的方法,这个启动失败通常被来自函数semget 的错误响应 No space left on device 搞得很让人迷惑。

有时候还可能有必要增大SEMMAP ,使之至少按照 SEMMNS 配置。这个参数定义信号灯资源映射的尺寸,可用的每个连续的信号灯块在这个映射中存放一条记录。每当一套信号灯被释放,那么它要么会加入到该映射中一条相连的已释放的块的入口中,要么注册成一条新的入口。如果映射填满了碎片,那么被释放的信号灯就丢失了(除非重起)。因此时间长信号灯空间的碎片了会导致可用的信号灯比应该有的信号灯少。

SEMMSL 参数,决定一套信号灯里可以有多少信号灯,

更改方法

缺省设置只适合小安装(缺省最大共享内存是 32 MB)。不过,其它的缺省值都相当大,通常不需要改变。最大的共享内存段设置可以用 sysctl 接口设置。 比如,要允许 128 MB,并且最大的总共享内存数为 2097152 页(缺省):

1
2
$ sysctl -w kernel.shmmax=134217728
$ sysctl -w kernel.shmall=2097152

你可以把这些设置放到 /etc/sysctl.conf 里,在重启后保持有效。

老版本里可能没有 sysctl 程序,但是同样的改变可以通过操作 /proc 文件系统来做:

1
2
$ echo 134217728 > /proc/sys/kernel/shmmax
$ echo 2097152 > /proc/sys/kernel/shmall

共享内存

http://blog.csdn.net/wc7620awjh/article/details/7721331

共享内存是被多个进程共享的一部分物理内存。共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容。原理图如下:

共享内存的实现分为两个步骤:
一、 创建共享内存,使用shmget函数。 二、 映射共享内存,将这段创建的共享内存映射到具体的进程空间去,使用shmat函数。

创建共享内存

1
int shmget(key_t key ,int size,int shmflg)

key标识共享内存的键值:0/IPC_PRIVATE。当key的取值为IPC_PRIVATE,则函数shmget将创建一块新的共享内存;如果key的取值为0,而参数中又设置了IPC_PRIVATE这个标志,则同样会创建一块新的共享内存。

返回值:如果成功,返回共享内存表示符,如果失败,返回-1。

映射共享内存

1
int shmat(int shmid,char *shmaddr,int flag)

参数:
shmid:shmget函数返回的共享存储标识符
flag:决定以什么样的方式来确定映射的地址(通常为0)

返回值:
如果成功,则返回共享内存映射到进程中的地址;如果失败,则返回-1。
共享内存解除映射

当一个进程不再需要共享内存时,需要把它从进程地址空间中多里。

1
int shmdt(char *shmaddr)

贡献内存实例如下:
实验要求:创建两个进程,在A进程中创建一个共享内存,并向其写入数据,通过B进程从共享内存中读取数据。

chm_com.h函数
1
2
3
4
5
6
7
#define TEXT_SZ 2048  

struct shared_use_st  
{  
	int written_by_you;  
	char some_text[TEXT_SZ];  
};  
读取进程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/ipc.h>  
#include <sys/shm.h>  
#include "shm_com.h"  
  
/* 
 * 程序入口 
 * */  
int main(void)  
{  
	int running=1;  
	void *shared_memory=(void *)0;  
	struct shared_use_st *shared_stuff;  
	int shmid;  
	/*创建共享内存*/  
	shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);  
	if(shmid==-1)  
	{  
		fprintf(stderr,"shmget failed\n");  
		exit(EXIT_FAILURE);  
	}  
  
	/*映射共享内存*/  
	shared_memory=shmat(shmid,(void *)0,0);  
	if(shared_memory==(void *)-1)  
	{  
		fprintf(stderr,"shmat failed\n");  
		exit(EXIT_FAILURE);  
	}  
	printf("Memory attached at %X\n",(int)shared_memory);  
  
	/*让结构体指针指向这块共享内存*/  
	shared_stuff=(struct shared_use_st *)shared_memory;  
  
	/*控制读写顺序*/  
	shared_stuff->written_by_you=0;  
	/*循环的从共享内存中读数据,直到读到“end”为止*/  
	while(running)  
	{  
	   if(shared_stuff->written_by_you)  
	   {  
		   printf("You wrote:%s",shared_stuff->some_text);  
		   sleep(1);  //读进程睡一秒,同时会导致写进程睡一秒,这样做到读了之后再写  
		   shared_stuff->written_by_you=0;  
		   if(strncmp(shared_stuff->some_text,"end",3)==0)  
		   {  
			   running=0; //结束循环  
		   }  
	   }  
	}  
	/*删除共享内存*/  
	if(shmdt(shared_memory)==-1)  
	{  
		fprintf(stderr,"shmdt failed\n");  
		exit(EXIT_FAILURE);  
	}  
	   exit(EXIT_SUCCESS);  
}  
写入进程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/ipc.h>  
#include <sys/shm.h>  
#include "shm_com.h"  
  
/* 
 * 程序入口 
 * */  
int main(void)  
{  
	int running=1;  
	void *shared_memory=(void *)0;  
	struct shared_use_st *shared_stuff;  
	char buffer[BUFSIZ];  
	int shmid;  
	/*创建共享内存*/  
	shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);  
	if(shmid==-1)  
	{  
		fprintf(stderr,"shmget failed\n");  
		exit(EXIT_FAILURE);  
	}  
  
	/*映射共享内存*/  
	shared_memory=shmat(shmid,(void *)0,0);  
	if(shared_memory==(void *)-1)  
	{  
		fprintf(stderr,"shmat failed\n");  
		exit(EXIT_FAILURE);  
	}  
	printf("Memory attached at %X\n",(int)shared_memory);  
  
	/*让结构体指针指向这块共享内存*/  
	shared_stuff=(struct shared_use_st *)shared_memory;  
	/*循环的向共享内存中写数据,直到写入的为“end”为止*/  
	while(running)  
	{  
		while(shared_stuff->written_by_you==1)  
		{  
			sleep(1);//等到读进程读完之后再写  
			printf("waiting for client...\n");  
		}  
		printf("Ener some text:");  
		fgets(buffer,BUFSIZ,stdin);  
		strncpy(shared_stuff->some_text,buffer,TEXT_SZ);  
		shared_stuff->written_by_you=1;  
		if(strncmp(buffer,"end",3)==0)  
		{  
			running=0;  //结束循环  
		}  
	}  
	/*删除共享内存*/  
	if(shmdt(shared_memory)==-1)  
	{  
		fprintf(stderr,"shmdt failed\n");  
		exit(EXIT_FAILURE);  
	}  
	exit(EXIT_SUCCESS);  
}  
运行

在一个终端中运行shm1,在另一个终端中运行shm2.当shm1运行起来之后,由于共享内存中没有数据可读,会处于等待状态

1
2
3
4
[root@localhost 2-4-4]# ./shm1
Memory attached at B7F9A000

/***阻塞***/

再向shm2运行的终端输入字符串

1
2
3
4
5
6
7
8
9
[root@localhost 2-4-4]# ./shm2
Memory attached at B7FD8000
Enter some text:Impossible is nothing
waiting for client。。。
waiting for client。。。
Enter some text:Anything is possible
waiting for client。。。
Ener some text:end
[root@localhost 2-4-4]#

shm1能够逐个从共享内存中巴他们读出来,知道双方晕倒字符串"end"后,两个程序都退出。

1
2
3
4
5
6
[root@localhost 2-4-4]# ./shm1
Memory attached at B7F9A000
You write:Impossible is nothing
You write:Anything is possible
You write:end
[root@localhost 2-4-4]#

以上运行过程中,红色表示在终端1中运行的结果,蓝色表示在终端2里面运行的结果。

ARM汇编简单样例

例一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.section .data
	.align 2
	.LC0: .string "gggghhhii"

.section .text
	.align 2
	.global main
	.type   main, %function
main:
	stmfd   sp!, {fp, lr} 
	ldr     r0, .L0 
	bl      puts
	ldmfd   sp!, {fp, pc} 

.L0: .word .LC0
1
2
3
android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-as b.s -o b.o

/home/kk/android/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ld -dynamic-linker /system/bin/linker -X -m armelf_linux_eabi -z noexecstack -z relro -z now crtbegin_dynamic.o -L/home/kk/android/android-ndk-r9d/platforms/android-19/arch-arm/usr/lib/ -L/home/kk/android/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6 -L/home/kk/android/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc -L/home/kk/android/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/lib b.o -lgcc -lc -ldl -lgcc crtend_android.o -o b.out

例二

a.c

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int i=12;
int j;

int main()
{
	i = 34; 
	j = 56; 
	printf("Hello World\n");
	return 0;
}
1
/home/kk/android/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc -I/home/kk/android/android-ndk-r9d/platforms/android-19/arch-arm/usr/include -L/home/kk/android/android-ndk-r9d/platforms/android-19/arch-arm/usr/lib/ -S a.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
.arch armv5te
.fpu softvfp
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 18, 4
.file   "a.c"
.global i
.data
.align  2
.type   i, %object
.size   i, 4
i:
.word   12  
.comm   j,4,4
.section        .rodata
.align  2
.LC0:
.ascii  "Hello World\000"
.text
.align  2
.global main
.type   main, %function
main:
@ args = 0, pretend = 0, frame = 0 
@ frame_needed = 1, uses_anonymous_args = 0 
stmfd   sp!, {fp, lr} 
add     fp, sp, #4
ldr     r3, .L2 
.LPIC0:
add     r3, pc, r3
ldr     r2, .L2+4
ldr     r2, [r3, r2] 
mov     r1, #34 
str     r1, [r2, #0] 
ldr     r2, .L2+8
ldr     r3, [r3, r2] 
mov     r2, #56 
str     r2, [r3, #0] 
ldr     r3, .L2+12
.LPIC1:
add     r3, pc, r3
mov     r0, r3
bl      puts(PLT)
mov     r3, #0
mov     r0, r3
ldmfd   sp!, {fp, pc}
.L3:
.align  2
.L2:
.word   _GLOBAL_OFFSET_TABLE_-(.LPIC0+8)
.word   i(GOT)
.word   j(GOT)
.word   .LC0-(.LPIC1+8)
.size   main, .-main
.ident  "GCC: (GNU) 4.6 20120106 (prerelease)"
.section        .note.GNU-stack,"",%progbits