<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/xsl/rss.xsl" type="text/xsl" media="screen"?>
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:ppp="http://blog.sohu.com/rss/module/ppp/"
	>

	<channel>
		<title>fitren</title>
		<link>http://fitren.blog.sohu.com/</link>
		<description><![CDATA[若不是因为风,雨不会美丽]]></description>
		<pubDate>Tue, 1 Jul 2008 09:32:22 +0800</pubDate>
		<generator>搜狐博客</generator>
		<ppp:ebi>d753ef3792</ppp:ebi>
		<image>
			<title>http://blog.sohu.com</title>
			<url>http://js.pp.sohu.com/ppp/blog/images/common/logo_150_60.gif</url>
			<link>http://blog.sohu.com/</link>
			<width>100</width>
			<height>43</height>
			<description>搜狐博客</description>
		</image>
		<item>
			<title>GtkEntry只允许数字输出,及输入变换pixbuf颜色</title>
			<link>http://fitren.blog.sohu.com/93178466.html</link>
			<comments>http://fitren.blog.sohu.com/93178466.html#comment</comments>
			<dc:creator>fitren</dc:creator>
			<pubDate>Tue, 1 Jul 2008 09:32:22 +0800</pubDate>
			<category>gtk</category>
			<guid>http://fitren.blog.sohu.com/93178466.html</guid>
			<description><![CDATA[<p>#include &lt;stdio.h&gt;<br />#include &lt;gtk/gtk.h&gt;<br />#include &lt;gdk/gdkkeysyms.h&gt;<br />#include &lt;stdlib.h&gt;//malloc<br />typedef struct {<br />&nbsp;GtkWidget *image;<br />&nbsp;GdkColor color;<br />&nbsp;GdkPixbuf *pixbuf;<br />&nbsp;int entry_type;<br />}tr_data;<br />gboolean key_filter(GtkWidget *entry,GdkEventKey *event,gpointer data)//number only<br />{<br />&nbsp;switch(event-&gt;keyval)<br />&nbsp;{<br />&nbsp;&nbsp;case GDK_0:<br />&nbsp;&nbsp;case GDK_1:<br />&nbsp;&nbsp;case GDK_2:<br />&nbsp;&nbsp;case GDK_3:<br />&nbsp;&nbsp;case GDK_4:<br />&nbsp;&nbsp;case GDK_5:<br />&nbsp;&nbsp;case GDK_6:<br />&nbsp;&nbsp;case GDK_7:<br />&nbsp;&nbsp;case GDK_8:<br />&nbsp;&nbsp;case GDK_9:<br />&nbsp;&nbsp;case GDK_KP_0:<br />&nbsp;&nbsp;case GDK_KP_1:<br />&nbsp;&nbsp;case GDK_KP_2:<br />&nbsp;&nbsp;case GDK_KP_3:<br />&nbsp;&nbsp;case GDK_KP_4:<br />&nbsp;&nbsp;case GDK_KP_5:<br />&nbsp;&nbsp;case GDK_KP_6:<br />&nbsp;&nbsp;case GDK_KP_7:<br />&nbsp;&nbsp;case GDK_KP_8:<br />&nbsp;&nbsp;case GDK_KP_9:<br />&nbsp;&nbsp;case GDK_BackSpace:<br />&nbsp;&nbsp;case GDK_Return:<br />&nbsp;&nbsp;case GDK_KP_Enter:<br />&nbsp;&nbsp;case GDK_KP_Space:<br />&nbsp;&nbsp;case GDK_Left:<br />&nbsp;&nbsp;case GDK_Right:<br />&nbsp;&nbsp;case GDK_Up:<br />&nbsp;&nbsp;case GDK_Down:<br />&nbsp;&nbsp;case GDK_Delete:<br />&nbsp;&nbsp;case GDK_Home:<br />&nbsp;&nbsp;case GDK_End:<br />&nbsp;&nbsp;case GDK_Tab:<br />&nbsp;&nbsp;&nbsp;return FALSE;break;<br />&nbsp;&nbsp;default:<br />&nbsp;&nbsp;&nbsp;return TRUE ;break;<br />&nbsp;}<br />}<br />void edited(GtkWidget *entry,gpointer data)<br />{<br />&nbsp;tr_data *td = (tr_data *)data;<br />&nbsp;int val=0;<br />&nbsp;const gchar *entry_name = NULL;<br />&nbsp;entry_name = gtk_widget_get_name(entry);<br />&nbsp;if(!strcmp(entry_name ,&quot;entry1&quot;))<br />&nbsp;&nbsp;td-&gt;entry_type = 0;<br />&nbsp;else<br />&nbsp;{<br />&nbsp;&nbsp;if(!strcmp(entry_name,&quot;entry2&quot;))<br />&nbsp;&nbsp;&nbsp;td-&gt;entry_type = 1;<br />&nbsp;&nbsp;else<br />&nbsp;&nbsp;&nbsp;td-&gt;entry_type = 2;<br />&nbsp;}<br />&nbsp;val = atoi(gtk_entry_get_text(GTK_ENTRY(entry)));<br />&nbsp;switch(td-&gt;entry_type)<br />&nbsp;{<br />&nbsp;&nbsp;case 0:<br />&nbsp;&nbsp;&nbsp;if(val&lt;=255 &amp;&amp; val &gt;= 0)<br />&nbsp;&nbsp;&nbsp;&nbsp;td-&gt;color.red = val;<br />&nbsp;&nbsp;&nbsp;else<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;td-&gt;color.red = 255;<br />&nbsp;&nbsp;&nbsp;&nbsp;gtk_entry_set_text (GTK_ENTRY(entry),&quot;255&quot;);<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;break;//r<br />&nbsp;&nbsp;case 1: <br />&nbsp;&nbsp;&nbsp;if(val&lt;=255 &amp;&amp; val &gt;= 0)<br />&nbsp;&nbsp;&nbsp;&nbsp;td-&gt;color.green = val;<br />&nbsp;&nbsp;&nbsp;else<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;td-&gt;color.green = 255;<br />&nbsp;&nbsp;&nbsp;&nbsp;gtk_entry_set_text (GTK_ENTRY(entry),&quot;255&quot;);<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;break;//g<br />&nbsp;&nbsp;case 2: <br />&nbsp;&nbsp;&nbsp;if(val&lt;=255 &amp;&amp; val &gt;= 0)<br />&nbsp;&nbsp;&nbsp;&nbsp;td-&gt;color.blue = val;<br />&nbsp;&nbsp;&nbsp;else<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;td-&gt;color.blue = 255;<br />&nbsp;&nbsp;&nbsp;&nbsp;gtk_entry_set_text (GTK_ENTRY(entry),&quot;255&quot;);<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;break;//b<br />&nbsp;&nbsp;default:break;<br />&nbsp;}<br />&nbsp;gint32 pixel = 0;<br />&nbsp;pixel = (td-&gt;color.red)&lt;&lt;24|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(td-&gt;color.green)&lt;&lt;16|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(td-&gt;color.blue)&lt;&lt;8;<br />&nbsp;gdk_pixbuf_fill(td-&gt;pixbuf,pixel);<br />&nbsp;gtk_image_set_from_pixbuf(GTK_IMAGE(td-&gt;image),td-&gt;pixbuf);&nbsp;<br />}<br />int main(int argc,char *argv[])<br />{<br />&nbsp; GtkWidget *window1;<br />&nbsp; GtkWidget *hbox1;<br />&nbsp; GtkWidget *entry1;<br />&nbsp; GtkWidget *entry2;<br />&nbsp; GtkWidget *entry3;<br />&nbsp;GtkWidget *image1;</p>
<p>&nbsp;tr_data *td = malloc(sizeof(tr_data));<br />&nbsp;gtk_init(&amp;argc,&amp;argv);<br />&nbsp; window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);<br />&nbsp; gtk_window_set_title (GTK_WINDOW (window1),&quot;window1&quot;);<br />&nbsp;g_signal_connect(window1,&quot;delete_event&quot;,G_CALLBACK(gtk_main_quit),NULL);<br />&nbsp;gtk_widget_show(window1);</p>
<p>&nbsp; hbox1 = gtk_hbox_new (FALSE, 0);<br />&nbsp; gtk_widget_show (hbox1);<br />&nbsp; gtk_container_add (GTK_CONTAINER (window1), hbox1);</p>
<p>&nbsp; entry1 = gtk_entry_new ();<br />&nbsp;gtk_widget_set_name(entry1,&quot;entry1&quot;);<br />&nbsp; gtk_widget_show (entry1);<br />&nbsp; gtk_box_pack_start (GTK_BOX (hbox1), entry1, TRUE, TRUE, 0);<br />&nbsp; gtk_widget_set_size_request (entry1, 20, -1);<br />&nbsp; gtk_entry_set_max_length (GTK_ENTRY (entry1), 3);<br />&nbsp; gtk_entry_set_text (GTK_ENTRY (entry1), &quot;255&quot;);<br />&nbsp;g_signal_connect(entry1,&quot;key-press-event&quot;,G_CALLBACK(key_filter),td);<br />&nbsp;g_signal_connect(entry1,&quot;changed&quot;,G_CALLBACK(edited),td);</p>
<p>&nbsp; entry2 = gtk_entry_new ();<br />&nbsp;gtk_widget_set_name(entry2,&quot;entry2&quot;);<br />&nbsp; gtk_widget_show (entry2);<br />&nbsp; gtk_box_pack_start (GTK_BOX (hbox1), entry2, TRUE, TRUE, 0);<br />&nbsp; gtk_widget_set_size_request (entry2, 20, -1);<br />&nbsp; gtk_entry_set_max_length (GTK_ENTRY (entry2), 3);<br />&nbsp; gtk_entry_set_text (GTK_ENTRY (entry2), &quot;0&quot;);<br />&nbsp;g_signal_connect(entry2,&quot;key-press-event&quot;,G_CALLBACK(key_filter),td);<br />&nbsp;g_signal_connect(entry2,&quot;changed&quot;,G_CALLBACK(edited),td);</p>
<p>&nbsp; entry3 = gtk_entry_new ();<br />&nbsp;gtk_widget_set_name(entry3,&quot;entry3&quot;);<br />&nbsp; gtk_widget_show (entry3);<br />&nbsp; gtk_box_pack_start (GTK_BOX (hbox1), entry3, TRUE, TRUE, 0);<br />&nbsp; gtk_widget_set_size_request (entry3, 20, -1);<br />&nbsp; gtk_entry_set_max_length (GTK_ENTRY (entry3), 3);<br />&nbsp; gtk_entry_set_text (GTK_ENTRY (entry3), &quot;0&quot;);<br />&nbsp;g_signal_connect(entry3,&quot;key-press-event&quot;,G_CALLBACK(key_filter),td);<br />&nbsp;g_signal_connect(entry3,&quot;changed&quot;,G_CALLBACK(edited),td);</p>
<p>&nbsp;GdkPixbuf *pixbuf;<br />&nbsp;pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,FALSE,8,24,24);<br />&nbsp;gint32 pixel = 0;<br />&nbsp;GdkColor color;<br />&nbsp;color.red = 0xff;<br />&nbsp;color.green = 0x00;<br />&nbsp;color.blue = 0x00;<br />&nbsp;pixel = (color.red)&lt;&lt;24|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(color.green)&lt;&lt;16|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(color.blue)&lt;&lt;8;<br />&nbsp;gdk_pixbuf_fill(pixbuf,pixel);</p>
<p>&nbsp;image1 = gtk_image_new_from_pixbuf(pixbuf);<br />&nbsp; gtk_widget_show (image1);<br />&nbsp; gtk_box_pack_start (GTK_BOX (hbox1), image1, TRUE, TRUE, 0);</p>
<p>&nbsp;td-&gt;image = image1;<br />&nbsp;td-&gt;color = color;<br />&nbsp;td-&gt;pixbuf = pixbuf;</p>
<p>&nbsp;gtk_main();<br />&nbsp;return 0;<br />}<br /></p>
<p>&nbsp;</p>]]></description>
		</item>
		    
		
		<item>
			<title>libglade用法</title>
			<link>http://fitren.blog.sohu.com/91253871.html</link>
			<comments>http://fitren.blog.sohu.com/91253871.html#comment</comments>
			<dc:creator>fitren</dc:creator>
			<pubDate>Fri, 27 Jun 2008 13:37:25 +0800</pubDate>
			<category>gtk</category>
			<guid>http://fitren.blog.sohu.com/91253871.html</guid>
			<description><![CDATA[<p>主函数:</p>
<p>#include &lt;stdio.h&gt;<br />#include &lt;gtk/gtk.h&gt;<br />#include &lt;glade/glade.h&gt;<br />#include &lt;glib.h&gt;<br />#include &lt;libintl.h&gt;//gettext support<br />#define GLADE_FILE &quot;test.glade&quot;<br />#define PACKAGE &quot;test.glade&quot;<br />#define LOCALEDIR &quot;./po&quot;<br />#define _(string) gettext(string)<br />#define N_(string) string<br />void button_clicked(GtkWidget *b)//这个callback函数在.glade声明,此处没有调用处<br />{<br />&nbsp;printf(&quot;%s\n&quot;,gtk_widget_get_name(b));<br />&nbsp;//gtk_widget_set_sensitive(b,FALSE);<br />}<br />int main(int argc,char *argv[])<br />{<br />&nbsp;gtk_set_locale();<br />&nbsp;bindtextdomain(PACKAGE,LOCALEDIR);<br />&nbsp;bind_textdomain_codeset(PACKAGE,&quot;utf-8&quot;);</p>
<p>&nbsp;GtkWidget *window;<br />&nbsp;GladeXML *xml;<br />&nbsp;gtk_init(&amp;argc,&amp;argv);</p>
<p>&nbsp;xml = glade_xml_new(GLADE_FILE,NULL,NULL);<br />&nbsp;glade_xml_signal_autoconnect(xml);<br />&nbsp;<br />&nbsp;char *title=&quot;test abcedfg&quot;;<br />&nbsp;GtkWidget *w = glade_xml_get_widget(xml,&quot;window1&quot;);<br />&nbsp;gtk_window_set_title(GTK_WINDOW(w),title);<br />&nbsp;g_signal_connect(w,&quot;delete_event&quot;,G_CALLBACK(gtk_main_quit),NULL);<br />&nbsp;free(title);<br />&nbsp;<br />&nbsp;gtk_container_remove(GTK_CONTAINER(w),glade_xml_get_widget(xml,&quot;button1&quot;));<br />&nbsp;GtkWidget *box = gtk_vbox_new(FALSE,0);<br />&nbsp;gtk_widget_show(box);<br />&nbsp;gtk_container_add(GTK_CONTAINER(w),box);</p>
<p><br />&nbsp;GtkWidget *button1 = gtk_button_new_from_stock(&quot;gtk-quit&quot;);<br />&nbsp;gtk_widget_show(button1);<br />&nbsp;gtk_box_pack_start(GTK_BOX(box),button1,0,FALSE,FALSE);</p>
<p>&nbsp;button1 = gtk_button_new_from_stock(&quot;gtk-ok&quot;);<br />&nbsp;gtk_widget_show(button1);<br />&nbsp;gtk_box_pack_start(GTK_BOX(box),button1,100,FALSE,FALSE);</p>
<p>&nbsp;xml = glade_xml_new(&quot;create_win.glade&quot;,&quot;vbox_win_create&quot;,NULL);//加载另外一个.glade文件，但不被显示出来 ，并取用其中的一个widget-vbox_win_create<br />&nbsp;glade_xml_signal_autoconnect(xml);</p>
<p>&nbsp;GtkWidget *vb = glade_xml_get_widget(xml,&quot;vbox_win_create&quot;);<br />&nbsp;gtk_box_pack_start(GTK_BOX(box),vb,0,FALSE,FALSE);<br />&nbsp;<br />&nbsp;xml = glade_xml_new(&quot;create_win.glade&quot;,&quot;frame_type&quot;,NULL);<br />&nbsp;glade_xml_signal_autoconnect(xml);<br />&nbsp;GtkWidget *frame = glade_xml_get_widget(xml,&quot;frame_type&quot;);<br />&nbsp;gtk_box_pack_start(GTK_BOX(box),frame,0,FALSE,FALSE);</p>
<p>&nbsp;gtk_main();<br />&nbsp;return 0;<br />}<br /></p>
<p>&nbsp;</p>
<p>Makefile:</p>
<p>CC=gcc<br />PRO=load_libglade<br />SRC=load_libglade.c<br />LIBS=`pkg-config --libs libglade-2.0`<br />CFLAGS=`pkg-config --cflags libglade-2.0`<br />OPTIONS=-rdynamic <br />all:$(SRC)<br />&nbsp;$(CC) -o $(PRO) $(SRC) $(CFLAGS) $(LIBS) $(OPTIONS)<br />.PHONY:clean<br />clean:<br />&nbsp;@rm -rf *~ $(PRO)<br /></p>
<p>&nbsp;</p>]]></description>
		</item>
		    
		
		<item>
			<title>gtk 文件复制及progress bar</title>
			<link>http://fitren.blog.sohu.com/90351889.html</link>
			<comments>http://fitren.blog.sohu.com/90351889.html#comment</comments>
			<dc:creator>fitren</dc:creator>
			<pubDate>Tue, 17 Jun 2008 16:36:22 +0800</pubDate>
			<category>gtk</category>
			<guid>http://fitren.blog.sohu.com/90351889.html</guid>
			<description><![CDATA[<p>#include &lt;stdio.h&gt;<br />#include &lt;unistd.h&gt;<br />#include &lt;sys/stat.h&gt;<br />#include &lt;sys/types.h&gt;<br />#include &lt;fcntl.h&gt;<br />#include &lt;stdlib.h&gt;//malloc<br />#define BUFSIZE 1024<br />#define SRC &quot;scmj.zip.s&quot;<br />char DES[16];<br />#include &lt;gtk/gtk.h&gt;<br />#include &lt;string.h&gt;//strcat<br />#define BUFSIZE 1024<br />int tmp = 0;//copy后新建文件的名字自增参数<br />void clean(gpointer data)//释放指针,并退出gtk<br />{<br />&nbsp;free(data);<br />&nbsp;gtk_main_quit();<br />}<br />typedef struct _tr_data //callback函数传递的指针结构,不想用全局变量^_^<br />{<br />&nbsp;GtkWidget *b;<br />&nbsp;GtkWidget *pbar;<br />&nbsp;GtkWidget *q;<br />&nbsp;int ip;<br />&nbsp;int op;<br />&nbsp;int count;<br />&nbsp;int total;<br />}tran_data;<br />int die (char *str)//文件读写失败<br />{<br />&nbsp;printf(&quot;%s\n&quot;,str);<br />&nbsp;return 1;<br />}<br />int idle_fuc(gpointer data)//循环<br />{<br />&nbsp;tran_data *td = (tran_data *)(data);<br />&nbsp;gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(td-&gt;pbar),(float)td-&gt;count/td-&gt;total);<br />&nbsp;char tmp[16];<br />&nbsp;sprintf(tmp,&quot;%.2f&quot;,(float)td-&gt;count*100/(float)td-&gt;total);<br />&nbsp;strcat(tmp,&quot;%&quot;);<br />&nbsp;gtk_progress_bar_set_text(GTK_PROGRESS_BAR(td-&gt;pbar),tmp);<br />&nbsp;int size;<br />&nbsp;char *c = malloc(BUFSIZE);<br />&nbsp;size = read(td-&gt;ip,c,BUFSIZE);<br />&nbsp;if(!size)<br />&nbsp;{<br />&nbsp;&nbsp;gtk_progress_bar_set_text(GTK_PROGRESS_BAR(td-&gt;pbar),&quot;Done!&quot;);<br />&nbsp;&nbsp;gtk_widget_set_sensitive(td-&gt;b,TRUE);<br />&nbsp;&nbsp;gtk_widget_set_sensitive(td-&gt;q,TRUE);<br />&nbsp;&nbsp;free(c);&nbsp;<br />&nbsp;&nbsp;return FALSE;<br />&nbsp;}<br />&nbsp;write(td-&gt;op,c,size);<br />&nbsp;td-&gt;count+=size;<br />&nbsp;return TRUE;<br />}<br />void button_clicked(gpointer data)//每次button clicked 的时候进行新的一次copy<br />{<br />&nbsp;tmp++;//change destination file name<br />&nbsp;tran_data *td = (tran_data *)data;<br />&nbsp;td-&gt;count = 0;&nbsp;<br />&nbsp;struct stat *buf;<br />&nbsp;buf = malloc(sizeof(struct stat));<br />&nbsp;lstat(SRC,buf);<br />&nbsp;td-&gt;total = buf-&gt;st_size;<br />&nbsp;free(buf);<br />&nbsp;sprintf(DES,&quot;%d&quot;,tmp);<br />&nbsp;strcat(DES,&quot;.zip&quot;);<br />&nbsp;td-&gt;ip = open(SRC,O_RDONLY);<br />&nbsp;td-&gt;op = open(DES,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);<br />&nbsp;if(td-&gt;ip == -1) <br />&nbsp;&nbsp;die(&quot;Open input File Faild&quot;);<br />&nbsp;if(td-&gt;op == -1) <br />&nbsp;&nbsp;die(&quot;Open Output File Faild&quot;);<br />&nbsp;gtk_widget_set_sensitive(td-&gt;b,FALSE);//保证在copy的过程中两个按钮不能作其它事情,直到copy完成<br />&nbsp;gtk_widget_set_sensitive(td-&gt;q,FALSE);<br />&nbsp;td-&gt;count = 0;<br />&nbsp;g_idle_add(idle_fuc,td);//gtk 循环处理调用<br />}<br />int main(int argc,char *argv[])//主程序<br />{<br />&nbsp;gtk_init (&amp;argc,&amp;argv);<br />&nbsp;GtkWidget *w = gtk_window_new(GTK_WINDOW_TOPLEVEL);<br />&nbsp;gtk_widget_show(w);</p>
<p>&nbsp;GtkWidget *box = gtk_vbox_new(FALSE,0);<br />&nbsp;gtk_container_add(GTK_CONTAINER(w),box);<br />&nbsp;gtk_widget_show(box);</p>
<p>&nbsp;GtkWidget *b = gtk_button_new_from_stock(&quot;gtk-execute&quot;);<br />&nbsp;gtk_box_pack_start(GTK_BOX(box),b,FALSE,FALSE,0);<br />&nbsp;gtk_widget_show(b);<br />&nbsp;<br />&nbsp;GtkWidget *pbar = gtk_progress_bar_new();<br />&nbsp;gtk_box_pack_start(GTK_BOX(box),pbar,FALSE,FALSE,0);<br />&nbsp;gtk_progress_bar_set_text(GTK_PROGRESS_BAR(pbar),&quot;Click button to start copy&quot;);</p>
<p>&nbsp;GtkWidget *q = gtk_button_new_from_stock(&quot;gtk-quit&quot;);<br />&nbsp;gtk_box_pack_start(GTK_BOX(box),q,FALSE,FALSE,0);<br />&nbsp;gtk_widget_show(q);<br />&nbsp;<br />&nbsp;tran_data *td = malloc(sizeof(tran_data));//初始化结构的一些成员,便于在callback函数中传递<br />&nbsp;td-&gt;b = b;<br />&nbsp;td-&gt;pbar = pbar;<br />&nbsp;td-&gt;q = q;<br />&nbsp;g_signal_connect_swapped(b,&quot;clicked&quot;,G_CALLBACK(button_clicked),td);<br />&nbsp;g_signal_connect_swapped(w,&quot;delete_event&quot;,G_CALLBACK(clean),td);<br />&nbsp;g_signal_connect_swapped(q,&quot;clicked&quot;,G_CALLBACK(clean),td);<br />&nbsp;gtk_widget_show(pbar);</p>
<p>&nbsp;gtk_main();<br />&nbsp;return 0;<br />}</p>]]></description>
		</item>
		    
		
		<item>
			<title>gtk sdl 旋转 缩放 图片</title>
			<link>http://fitren.blog.sohu.com/89901013.html</link>
			<comments>http://fitren.blog.sohu.com/89901013.html#comment</comments>
			<dc:creator>fitren</dc:creator>
			<pubDate>Thu, 12 Jun 2008 12:43:55 +0800</pubDate>
			<guid>http://fitren.blog.sohu.com/89901013.html</guid>
			<description><![CDATA[<p>//程序source code</p>
<p>#include &lt;stdio.h&gt;<br />#include &lt;string.h&gt;<br />#include &lt;SDL/SDL.h&gt;<br />#include &lt;SDL/SDL_image.h&gt;<br />#include &lt;gtk/gtk.h&gt;<br />#include &lt;SDL/SDL_rotozoom.h&gt;<br />#include &lt;gdk/gdkx.h&gt;//GDK_WINDOW_XWINDOW()<br />#include &lt;unistd.h&gt;&nbsp;&nbsp; //_exit()<br />#define WWIDTH 800<br />#define WHEIGHT 600<br />#define SDL_WIDTH 600<br />#define SDL_HEIGHT 480</p>
<p>SDL_Surface *screen = NULL;<br />int draw_flag = 1;<br />int flag_zoom = 1;<br />void draw_render();<br />void clear_screen(SDL_Surface *screen);</p>
<p>void picture_zoom (SDL_Surface *screen, SDL_Surface *picture,float zoomx,float zoomy,Uint32 interval) <br />{<br />&nbsp;//handle_event();<br />&nbsp;clear_screen(screen);<br />&nbsp;SDL_Surface *rotozoom_picture = NULL;<br />&nbsp;SDL_Rect dest;<br />&nbsp;&nbsp; &nbsp;if ((rotozoom_picture=zoomSurface (picture, zoomx,zoomy, 1))!=NULL) {<br />&nbsp;&nbsp;dest.x = (screen-&gt;w - rotozoom_picture-&gt;w)/2;;<br />&nbsp;&nbsp;dest.y = (screen-&gt;h - rotozoom_picture-&gt;h)/2;<br />&nbsp;&nbsp;dest.w = rotozoom_picture-&gt;w;<br />&nbsp;&nbsp;dest.h = rotozoom_picture-&gt;h;<br />&nbsp;&nbsp;if ( SDL_BlitSurface(rotozoom_picture, NULL, screen, &amp;dest) &lt; 0 ) {<br />&nbsp;&nbsp;&nbsp;fprintf(stderr, &quot;Blit failed: %s\n&quot;, SDL_GetError());<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;SDL_FreeSurface(rotozoom_picture);<br />&nbsp;}<br />&nbsp;/* Display by flipping screens */<br />&nbsp;SDL_Flip(screen);<br />&nbsp;SDL_Delay(interval);<br />}<br />void picture_rotozoom (SDL_Surface *screen, SDL_Surface *picture,int angle,float zoomx,float zoomy,Uint32 interval) <br />{<br />&nbsp;//handle_event();<br />&nbsp;clear_screen(screen);<br />&nbsp;SDL_Surface *rotozoom_picture = NULL;<br />&nbsp;SDL_Rect dest;<br />&nbsp; if ((rotozoom_picture=rotozoomSurfaceXY (picture, angle, zoomx, zoomy, 1))!=NULL) {<br />&nbsp;&nbsp;dest.x = (screen-&gt;w - rotozoom_picture-&gt;w)/2;;<br />&nbsp;&nbsp;dest.y = (screen-&gt;h - rotozoom_picture-&gt;h)/2;<br />&nbsp;&nbsp;dest.w = rotozoom_picture-&gt;w;<br />&nbsp;&nbsp;dest.h = rotozoom_picture-&gt;h;<br />&nbsp;&nbsp;if ( SDL_BlitSurface(rotozoom_picture, NULL, screen, &amp;dest) &lt; 0 ) {<br />&nbsp;&nbsp;&nbsp;fprintf(stderr, &quot;Blit failed: %s\n&quot;, SDL_GetError());<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;SDL_FreeSurface(rotozoom_picture);<br />&nbsp;}</p>
<p>&nbsp;SDL_Flip(screen);<br />&nbsp;SDL_Delay(interval);<br />}<br />void clear_screen(SDL_Surface *screen)<br />{<br />&nbsp;int i;<br />&nbsp;/* Set the screen to color */<br />&nbsp;if ( SDL_LockSurface(screen) == 0 ) {<br />&nbsp;&nbsp;Uint8 *pixels;<br />&nbsp;&nbsp;pixels = (Uint8 *)screen-&gt;pixels;<br />&nbsp;&nbsp;for ( i=0; i&lt;screen-&gt;h; ++i ) {<br />&nbsp;&nbsp;&nbsp;memset(pixels, 0x00,<br />&nbsp;&nbsp;&nbsp;&nbsp;screen-&gt;w*screen-&gt;format-&gt;BytesPerPixel);<br />&nbsp;&nbsp;&nbsp;pixels += screen-&gt;pitch;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;SDL_UnlockSurface(screen);<br />&nbsp;}<br />}<br />void button_zoom_clicked(GtkWidget *b)<br />{&nbsp;<br />&nbsp;if(draw_flag)<br />&nbsp;&nbsp;g_idle_add((GSourceFunc)draw_render, b);<br />&nbsp;draw_flag = 0;<br />&nbsp;flag_zoom = 1;<br />&nbsp;gtk_widget_set_sensitive(b,FALSE);<br />&nbsp;GList* cl = gtk_container_get_children (GTK_CONTAINER(b-&gt;parent));<br />&nbsp;int i;<br />&nbsp;int len = g_list_length(cl);<br />//&nbsp;const char *b_label = gtk_button_get_label(GTK_BUTTON(cl-&gt;data));<br />&nbsp;for(i = 0;i&lt;len;i++)<br />&nbsp;{<br />//&nbsp;&nbsp;const gchar *label = gtk_button_get_label(GTK_BUTTON(cl-&gt;data));<br />//&nbsp;&nbsp;if(strcmp(label,b_label))<br />&nbsp;&nbsp;&nbsp;gtk_widget_set_sensitive(GTK_WIDGET(cl-&gt;data),FALSE);<br />&nbsp;&nbsp;cl = cl-&gt;next ;<br />&nbsp;}<br />}<br />void button_rotate_clicked(GtkWidget *b)<br />{&nbsp;<br />&nbsp;if(draw_flag)<br />&nbsp;&nbsp;g_idle_add((GSourceFunc)draw_render, b);<br />&nbsp;draw_flag = 0;<br />&nbsp;flag_zoom = 0;<br />&nbsp;gtk_widget_set_sensitive(b,FALSE);<br />&nbsp;GList* cl = gtk_container_get_children (GTK_CONTAINER(b-&gt;parent));<br />&nbsp;int i;<br />&nbsp;int len = g_list_length(cl);<br />//&nbsp;const char *b_label = gtk_button_get_label(GTK_BUTTON(cl-&gt;data));<br />&nbsp;for(i = 0;i&lt;len;i++)<br />&nbsp;{<br />//&nbsp;&nbsp;const gchar *label = gtk_button_get_label(GTK_BUTTON(cl-&gt;data));<br />&nbsp;//&nbsp;if(strcmp(label,b_label))<br />&nbsp;&nbsp;&nbsp;gtk_widget_set_sensitive(GTK_WIDGET(cl-&gt;data),FALSE);<br />&nbsp;&nbsp;cl = cl-&gt;next ;<br />&nbsp;}<br />}<br />SDL_Surface *Load_Image(char *filepath)<br />{<br />&nbsp;SDL_Surface *li = IMG_Load(filepath);<br />&nbsp;SDL_Surface *op = NULL;<br />&nbsp;if(li !=NULL)<br />&nbsp;{<br />&nbsp;&nbsp;op = SDL_DisplayFormat(li);<br />&nbsp;&nbsp;SDL_FreeSurface(li);<br />&nbsp;&nbsp;if(op !=NULL)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;Uint32 colorkey = SDL_MapRGB(op-&gt;format,0,0x00,0x00);<br />&nbsp;&nbsp;&nbsp;SDL_SetColorKey(op,SDL_SRCCOLORKEY,colorkey);<br />&nbsp;&nbsp;}<br />&nbsp;}<br />&nbsp;return op;<br />}<br />void draw_render(GtkWidget *b)<br />{<br />&nbsp;SDL_Surface *img1 =NULL;<br />&nbsp;img1 = Load_Image(&quot;dots.png&quot;);<br />&nbsp;int i ;<br />&nbsp;Uint32 interval = 50;</p>
<p>&nbsp;if(!draw_flag)<br />&nbsp;{<br />&nbsp;&nbsp;for(i = 1;i&lt;20;i++)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;if(flag_zoom)<br />&nbsp;&nbsp;&nbsp;&nbsp;picture_zoom(screen,img1,(float)i/10,(float)i/10,interval);<br />&nbsp;&nbsp;&nbsp;else<br />&nbsp;&nbsp;&nbsp;&nbsp;picture_rotozoom(screen,img1,i*36,(float)i/10,(float)i/10,interval);<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;/*if(SDL_MUSTLOCK(screen))<br />&nbsp;&nbsp;&nbsp;if(SDL_LockSurface(screen)&lt;0)<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&quot;Can not LockSurface:%s\n&quot;,SDL_GetError);<br />&nbsp;&nbsp;&nbsp;&nbsp;SDL_ClearError();<br />&nbsp;&nbsp;&nbsp;&nbsp;return ;<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;int tick = SDL_GetTicks();<br />&nbsp;&nbsp;&nbsp;int i,j,yofs,ofs;</p>
<p>&nbsp;&nbsp;yofs = 0;<br />&nbsp;&nbsp;for(i = 0;i&lt;SDL_HEIGHT;i++)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;for(j = 0,ofs = yofs;j&lt;SDL_WIDTH;j++,ofs++)<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;((unsigned int *)screen-&gt;pixels)[ofs] = i * i + j*j + tick;<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;yofs += screen-&gt;pitch/4;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;if(SDL_MUSTLOCK(screen))<br />&nbsp;&nbsp;&nbsp;SDL_UnlockSurface(screen);*/<br />&nbsp;&nbsp; <br />&nbsp;}<br />&nbsp;else<br />&nbsp;{<br />&nbsp;&nbsp;clear_screen(screen);<br />&nbsp;&nbsp;GList* cl = gtk_container_get_children (GTK_CONTAINER(b-&gt;parent));<br />&nbsp;&nbsp;int i;<br />&nbsp;&nbsp;int len = g_list_length(cl);<br />&nbsp;&nbsp;for(i = 0;i&lt;len;i++)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;gtk_widget_set_sensitive(GTK_WIDGET(cl-&gt;data),TRUE);<br />&nbsp;&nbsp;&nbsp;cl = cl-&gt;next ;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;i = 10;<br />&nbsp;&nbsp;picture_zoom(screen,img1,(float)i/10,(float)i/10,interval);<br />&nbsp;}<br />&nbsp;draw_flag = 1;<br />&nbsp;SDL_UpdateRect(screen,0,0,SDL_WIDTH,SDL_HEIGHT);<br />}<br />void delete_event_fun()<br />{<br />&nbsp;gtk_main_quit();<br />&nbsp;SDL_Quit();<br />}</p>
<p>int main(int argc,char *argv[])<br />{<br />&nbsp;gtk_init(&amp;argc,&amp;argv);</p>
<p>&nbsp;GtkWidget *w = gtk_window_new(GTK_WINDOW_TOPLEVEL);<br />&nbsp;gtk_widget_set_size_request(w,WWIDTH,WHEIGHT);<br />&nbsp;gtk_widget_realize(w);//important<br />&nbsp;g_signal_connect(w,&quot;delete_event&quot;,delete_event_fun,NULL);</p>
<p>&nbsp;gtk_widget_add_events(w, GDK_BUTTON_PRESS_MASK);<br />&nbsp;<br />&nbsp;GtkWidget *fixed = gtk_fixed_new();<br />&nbsp;gtk_container_add(GTK_CONTAINER(w),fixed);<br />&nbsp;gtk_widget_show(fixed);</p>
<p>&nbsp;GtkWidget *b = gtk_button_new_with_label(&quot;Rotate&quot;);<br />&nbsp;gtk_fixed_put(GTK_FIXED(fixed),b,600,0);//position of button,you can costomsize it by your sdl screen position<br />&nbsp;gtk_widget_show(b);<br />&nbsp;g_signal_connect(b,&quot;clicked&quot;,G_CALLBACK(button_rotate_clicked),NULL);</p>
<p>&nbsp;b = gtk_button_new_with_label(&quot;Zoom&quot;);<br />&nbsp;gtk_fixed_put(GTK_FIXED(fixed),b,600,50);//position of button,you can costomsize it by your sdl screen position<br />&nbsp;gtk_widget_show(b);<br />&nbsp;g_signal_connect(b,&quot;clicked&quot;,G_CALLBACK(button_zoom_clicked),NULL);<br />&nbsp;<br />&nbsp;char wh [32];<br />&nbsp;sprintf(wh,&quot;SDL_WINDOWID=%ld&quot;,GDK_WINDOW_XWINDOW(w-&gt;window));//important<br />&nbsp;putenv(wh);</p>
<p>&nbsp;if ( SDL_Init(SDL_INIT_VIDEO) &lt; 0 ) {<br />&nbsp;&nbsp;fprintf(stderr,&quot;Couldn't initialize SDL: %s\n&quot;,SDL_GetError());<br />&nbsp;&nbsp;gtk_main_quit();<br />&nbsp;}</p>
<p>&nbsp;screen = SDL_SetVideoMode(SDL_WIDTH,SDL_HEIGHT,32,SDL_SWSURFACE);<br />&nbsp;gtk_widget_show(w);<br />&nbsp;gtk_main();&nbsp;<br />&nbsp;SDL_Quit();<br />&nbsp;return 0;<br />}<br /></p>
<p>Makefile:</p>
<p>CC=gcc<br />SRC=$(wildcard *.c)<br />LIBS=`pkg-config --libs gtk+-2.0` `sdl-config --libs` <br />CFLAGS=`pkg-config --cflags gtk+-2.0` `sdl-config --cflags` -lSDL_image -lSDL_gfx<br />#PRO=`for file in *.c ;do echo $file | cut -d'.' -f1;done;`<br />PRO=`echo *.c|cut -d'.' -f1`<br />all:$(SRC)<br />&nbsp;$(CC) $(SRC) $(LIBS) $(CFLAGS)<br />&nbsp;@mv a.out $(PRO);<br />.PHONY:clean<br />clean:<br />&nbsp;@rm&nbsp; -rf *~&nbsp; $(PRO) <br /></p>
<p>说明:</p>
<p>&nbsp; gtk和sdl结合使用,SDL主要用于图片的绘制,等效等,gtk主要用其widgets</p>
<p>&nbsp; 其中SDL要用到sdl_gfx库对图片进行处理</p>]]></description>
		</item>
		    
		
		<item>
			<title>SDL中画线,画圆以及填充的算法(出自计算机图形学,潘云鹤主编)</title>
			<link>http://fitren.blog.sohu.com/89718885.html</link>
			<comments>http://fitren.blog.sohu.com/89718885.html#comment</comments>
			<dc:creator>fitren</dc:creator>
			<pubDate>Tue, 10 Jun 2008 10:06:48 +0800</pubDate>
			<category>sdl</category>
			<guid>http://fitren.blog.sohu.com/89718885.html</guid>
			<description><![CDATA[<p>#include &quot;stdio.h&quot; <br />#include &quot;stdlib.h&quot;<br />#include &quot;string.h&quot;<br />#include &quot;SDL/SDL.h&quot;<br />#include &quot;windows.h&quot;<br />#include &quot;SDL/SDL_image.h&quot;<br />SDL_Surface *screen = NULL;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //屏幕接口<br />void put_pixel(SDL_Surface *surface, int x, int y, Uint32 pixel);<br />Uint32 get_pixel(SDL_Surface *surface, int x, int y);<br />void draw_point(SDL_Surface *screen,int x,int y,Uint32 color);<br />void seed_filling(SDL_Surface *screen,int i,int j,Uint32 color_fill,Uint32 boundary_color)<br />{<br />&nbsp;//没有成功<br />&nbsp;Uint32 c = get_pixel(screen,i,j);//得到i,j点的颜色<br />&nbsp;if((c != boundary_color)&amp;&amp;(c != color_fill))<br />&nbsp;{<br />&nbsp;&nbsp;//四邻法填充<br />&nbsp;&nbsp;put_pixel(screen,i,j,color_fill);<br />&nbsp;/*&nbsp;seed_filling(screen,i+1,j,color_fill,boundary_color);<br />&nbsp;&nbsp;seed_filling(screen,i-1,j,color_fill,boundary_color);<br />&nbsp;&nbsp;seed_filling(screen,i,j+1,color_fill,boundary_color);<br />&nbsp;&nbsp;seed_filling(screen,i,j-1,color_fill,boundary_color);*/<br />&nbsp;}<br />}<br />void plot_circle_points(SDL_Surface *screen,int xc,int yc,int x,int y,Uint32 c)<br />{<br />&nbsp;put_pixel(screen,xc+x,yc+y,c);<br />&nbsp;put_pixel(screen,xc-x,yc+y,c);<br />&nbsp;put_pixel(screen,xc+x,yc-y,c);<br />&nbsp;put_pixel(screen,xc-x,yc-y,c);<br />&nbsp;put_pixel(screen,xc+y,yc+x,c);<br />&nbsp;put_pixel(screen,xc-y,yc+x,c);<br />&nbsp;put_pixel(screen,xc+y,yc-x,c);<br />&nbsp;put_pixel(screen,xc-y,yc-x,c);<br />}<br />void bresenham_circle(SDL_Surface *screen,int xc,int yc,int radius,Uint32 c)<br />{<br />&nbsp;int x,y,p;<br />&nbsp;x = 0;<br />&nbsp;y = radius;<br />&nbsp;p = 3-2*radius;<br />&nbsp;while(x&lt;y)<br />&nbsp;{<br />&nbsp;&nbsp;plot_circle_points(screen,xc,yc,x,y,c);<br />&nbsp;&nbsp;if(p&lt;0)<br />&nbsp;&nbsp;&nbsp;p=p+4*x+6;<br />&nbsp;&nbsp;else<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;p=p+4*(x-y)+10;<br />&nbsp;&nbsp;&nbsp;y-=1;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;x+=1;<br />&nbsp;}<br />&nbsp;if(x == y)<br />&nbsp;&nbsp;plot_circle_points(screen,xc,yc,x,y,c);<br />}<br />void bresenham_line(SDL_Surface *screen,int x1,int y1,int x2,int y2,Uint32 c)<br />{<br />&nbsp;int dx,dy,x,y,p,const1,const2,inc,tmp;<br />&nbsp;dx = x2-x1;<br />&nbsp;dy = y2-y1;<br />&nbsp;if(dx*dy &gt;= 0)<br />&nbsp;&nbsp;inc = 1;<br />&nbsp;else<br />&nbsp;&nbsp;inc = -1;<br />&nbsp;if(abs(dx)&gt;abs(dy))<br />&nbsp;{<br />&nbsp;&nbsp;if(dx&lt;0)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;tmp = x1;<br />&nbsp;&nbsp;&nbsp;x1 = x2;<br />&nbsp;&nbsp;&nbsp;x2 = tmp;<br />&nbsp;&nbsp;&nbsp;tmp = y1;<br />&nbsp;&nbsp;&nbsp;y1 = y2;<br />&nbsp;&nbsp;&nbsp;y2 = tmp;<br />&nbsp;&nbsp;&nbsp;dx = -dx;<br />&nbsp;&nbsp;&nbsp;dy = -dy;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;p = 2*dy-dx;<br />&nbsp;&nbsp;const1 = 2*dy;<br />&nbsp;&nbsp;const2 = 2*(dy-dx);<br />&nbsp;&nbsp;x = x1;<br />&nbsp;&nbsp;y = y1;<br />&nbsp;&nbsp;put_pixel(screen,x,y,c);<br />&nbsp;&nbsp;while(x&lt;x2)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;x++;<br />&nbsp;&nbsp;&nbsp;if(p&lt;0)<br />&nbsp;&nbsp;&nbsp;&nbsp;p += const1;<br />&nbsp;&nbsp;&nbsp;else<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;y += inc;<br />&nbsp;&nbsp;&nbsp;&nbsp;p += const2;<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;put_pixel(screen,x,y,c);<br />&nbsp;&nbsp;}<br />&nbsp;}<br />&nbsp;else<br />&nbsp;{<br />&nbsp;&nbsp;if(dy&lt;0)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;tmp = x1;<br />&nbsp;&nbsp;&nbsp;x1 = x2;<br />&nbsp;&nbsp;&nbsp;x2 = tmp;<br />&nbsp;&nbsp;&nbsp;tmp = y1;<br />&nbsp;&nbsp;&nbsp;y1 = y2;<br />&nbsp;&nbsp;&nbsp;y2 = tmp;<br />&nbsp;&nbsp;&nbsp;dx = -dx;<br />&nbsp;&nbsp;&nbsp;dy = -dy;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;p = 2*dy-dx;<br />&nbsp;&nbsp;const1 = 2*dy;<br />&nbsp;&nbsp;const2 = 2*(dy-dx);<br />&nbsp;&nbsp;x = x1;<br />&nbsp;&nbsp;y = y1;<br />&nbsp;&nbsp;put_pixel(screen,x,y,c);<br />&nbsp;&nbsp;while(y&lt;y2)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;y++;<br />&nbsp;&nbsp;&nbsp;if(p&lt;0)<br />&nbsp;&nbsp;&nbsp;&nbsp;p += const1;<br />&nbsp;&nbsp;&nbsp;else<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;x+=inc;<br />&nbsp;&nbsp;&nbsp;&nbsp;p+=const2;<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;put_pixel(screen,x,y,c);<br />&nbsp;&nbsp;}<br />&nbsp;}<br />}<br />void dda_line(SDL_Surface *screen,int xa,int ya,int xb,int yb,Uint32 c)<br />{<br />&nbsp;float delta_x,delta_y,x,y;<br />&nbsp;int dx,dy,steps,k;<br />&nbsp;dx = xb-xa;<br />&nbsp;dy = yb-ya;<br />&nbsp;<br />&nbsp;if(abs(dx)&gt;abs(dy))<br />&nbsp;&nbsp;&nbsp;steps = abs(dx);<br />&nbsp;else<br />&nbsp;&nbsp;&nbsp;steps = abs(dy);<br />&nbsp;<br />&nbsp;delta_x = (float)dx/(float)steps;<br />&nbsp;delta_y = (float)dy/(float)steps;<br />&nbsp;x = xa;<br />&nbsp;y = ya;<br />&nbsp;put_pixel(screen,x,y,c);<br />&nbsp;for(k = 0;k&lt;steps;k++)<br />&nbsp;{<br />&nbsp;&nbsp;x+=delta_x;<br />&nbsp;&nbsp;y+=delta_y;<br />&nbsp;&nbsp;put_pixel(screen,x,y,c);<br />&nbsp;}<br />&nbsp;return ;<br />}<br />/*<br />&nbsp;* Return the pixel value at (x, y)<br />&nbsp;* NOTE: The surface must be locked before calling this!<br />&nbsp;*/<br />Uint32 get_pixel(SDL_Surface *surface, int x, int y)<br />{<br />&nbsp;&nbsp;&nbsp; int bpp = surface-&gt;format-&gt;BytesPerPixel;<br />&nbsp;&nbsp;&nbsp; /* Here p is the address to the pixel we want to retrieve */<br />&nbsp;&nbsp;&nbsp; Uint8 *p = (Uint8 *)surface-&gt;pixels + y * surface-&gt;pitch + x * bpp;</p>
<p>&nbsp;&nbsp;&nbsp; switch(bpp) {<br />&nbsp;&nbsp;&nbsp; case 1:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *p;</p>
<p>&nbsp;&nbsp;&nbsp; case 2:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *(Uint16 *)p;</p>
<p>&nbsp;&nbsp;&nbsp; case 3:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(SDL_BYTEORDER == SDL_BIG_ENDIAN)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return p[0] &lt;&lt; 16 | p[1] &lt;&lt; 8 | p[2];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return p[0] | p[1] &lt;&lt; 8 | p[2] &lt;&lt; 16;</p>
<p>&nbsp;&nbsp;&nbsp; case 4:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *(Uint32 *)p;</p>
<p>&nbsp;&nbsp;&nbsp; default:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* shouldn't happen, but avoids warnings */<br />&nbsp;&nbsp;&nbsp; }<br />}</p>
<p>/*<br />&nbsp;* Set the pixel at (x, y) to the given value<br />&nbsp;* NOTE: The surface must be locked before calling this!<br />&nbsp;*/<br />void put_pixel(SDL_Surface *surface, int x, int y, Uint32 pixel)<br />{<br />&nbsp;&nbsp;&nbsp; int bpp = surface-&gt;format-&gt;BytesPerPixel;<br />&nbsp;&nbsp;&nbsp; /* Here p is the address to the pixel we want to set */<br />&nbsp;&nbsp;&nbsp; Uint8 *p = (Uint8 *)surface-&gt;pixels + y * surface-&gt;pitch + x * bpp;</p>
<p>&nbsp;&nbsp;&nbsp; switch(bpp) {<br />&nbsp;&nbsp;&nbsp; case 1:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *p = pixel;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</p>
<p>&nbsp;&nbsp;&nbsp; case 2:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *(Uint16 *)p = pixel;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</p>
<p>&nbsp;&nbsp;&nbsp; case 3:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p[0] = (pixel &gt;&gt; 16) &amp; 0xff;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p[1] = (pixel &gt;&gt; 8) &amp; 0xff;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p[2] = pixel &amp; 0xff;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p[0] = pixel &amp; 0xff;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p[1] = (pixel &gt;&gt; 8) &amp; 0xff;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p[2] = (pixel &gt;&gt; 16) &amp; 0xff;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</p>
<p>&nbsp;&nbsp;&nbsp; case 4:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *(Uint32 *)p = pixel;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; }<br />}</p>
<p>void draw_point(SDL_Surface *screen,int x,int y,Uint32 color)<br />{<br />&nbsp;&nbsp;&nbsp; if ( SDL_MUSTLOCK(screen) ) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( SDL_LockSurface(screen) &lt; 0 ) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr, &quot;Can't lock screen: %s\n&quot;, SDL_GetError());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;put_pixel(screen, x, y, color);</p>
<p>&nbsp;&nbsp;&nbsp; if ( SDL_MUSTLOCK(screen) ) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SDL_UnlockSurface(screen);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; /* Update just the part of the display that we've changed */<br />&nbsp;&nbsp;&nbsp; SDL_UpdateRect(screen, x, y, 1, 1);</p>
<p>&nbsp;&nbsp;&nbsp; return;</p>
<p>}</p>
<p>void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )<br />{<br />&nbsp;SDL_Rect offset;<br />&nbsp;offset.x = x;<br />&nbsp;offset.y = y;<br />&nbsp;SDL_BlitSurface( source, NULL, destination, &amp;offset );<br />}<br />SDL_Surface *load_image( char *filename ) <br />{<br />&nbsp;&nbsp;&nbsp; //将图象暂时存储在这里<br />&nbsp;&nbsp;&nbsp; SDL_Surface* loadedImage = NULL;&nbsp; <br />&nbsp;&nbsp;&nbsp; //存储最佳的图象<br />&nbsp;&nbsp;&nbsp; SDL_Surface* optimizedImage = NULL;<br />&nbsp;//导入图象<br />&nbsp;&nbsp;&nbsp; loadedImage = IMG_Load( filename );<br />&nbsp;//如果导入图象不为空<br />&nbsp;&nbsp;&nbsp; if( loadedImage != NULL )<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //建立最佳的图象<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; optimizedImage = SDL_DisplayFormat( loadedImage );&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //释放老的图象<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SDL_FreeSurface( loadedImage );<br />&nbsp;&nbsp;if( optimizedImage != NULL )<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;//取得颜色码<br />&nbsp;&nbsp;&nbsp;Uint32 colorkey = SDL_MapRGB( optimizedImage-&gt;format, 0, 0, 0xFF );<br />&nbsp;&nbsp;&nbsp;//设置颜色码<br />&nbsp;&nbsp;&nbsp;SDL_SetColorKey( optimizedImage, SDL_RLEACCEL | SDL_SRCCOLORKEY, colorkey );<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;//返回最佳的图象<br />&nbsp;&nbsp;&nbsp; return optimizedImage;</p>
<p>}</p>
<p>int main( int argc, char* args[] )&nbsp;&nbsp; //主程序<br />{<br />&nbsp;&nbsp;&nbsp; char msg[500];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 得到系统消息<br />&nbsp;&nbsp;&nbsp; int done;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /* 初始化SDL */</p>
<p>&nbsp;&nbsp;&nbsp; if (SDL_Init (SDL_INIT_VIDEO) &lt; 0)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf (msg, &quot;不能初始化 SDL: %s\n&quot;, SDL_GetError ());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MessageBox (0, msg, &quot;Error&quot;, MB_ICONHAND); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit (1);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; atexit (SDL_Quit);&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; /* 设置 640x480 16-bits 图象模式 */</p>
<p>&nbsp;&nbsp;&nbsp; screen = SDL_SetVideoMode (800, 600, 32, SDL_SWSURFACE |SDL_DOUBLEBUF);<br />&nbsp;&nbsp;&nbsp; if (screen == NULL)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf (msg, &quot;不能设置成 640x480x16 图象模式: %s\n&quot;,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SDL_GetError ());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MessageBox (0, msg, &quot;Error&quot;, MB_ICONHAND); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit (2);<br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;//SDL_WM_ToggleFullScreen(screen);<br />/*&nbsp;SDL_VideoInfo *gvi = NULL;<br />&nbsp;gvi = SDL_GetVideoInfo();*/<br />&nbsp;<br />&nbsp;&nbsp; /*设置SDL窗口标题 */<br />&nbsp;//SDL_Surface *background=NULL;<br />&nbsp;//background=load_image(&quot;bg_pic.png&quot;);</p>
<p>&nbsp;&nbsp;&nbsp; SDL_WM_SetCaption (&quot;hello,the world&quot;, NULL);</p>
<p>&nbsp;int i,j;<br />&nbsp;Uint32 color = SDL_MapRGB(screen-&gt;format,0xff,0xff,0xff);<br />&nbsp;//对比以下两种画线算法所花费的时间dda vs bresenham,</p>
<p>//结果bresenham算法在画多条的时候比dda快将近一倍<br />&nbsp;Uint32 t1=SDL_GetTicks();<br />&nbsp;for(i = 0;i&lt;400;i++)<br />&nbsp;{<br />&nbsp;&nbsp;for(j = 0;j&lt;300;j++)<br />&nbsp;&nbsp;&nbsp;dda_line(screen,0,0,i,j,color);<br />&nbsp;}<br />&nbsp;Uint32 t2=SDL_GetTicks();</p>
<p>&nbsp;Uint32 t3=SDL_GetTicks();<br />&nbsp;for(i = 0;i&lt;400;i++)<br />&nbsp;{<br />&nbsp;&nbsp;for(j = 0;j&lt;300;j++)<br />&nbsp;&nbsp;&nbsp;bresenham_line(screen,0,0,i,j,color);<br />&nbsp;}<br />&nbsp;Uint32 t4=SDL_GetTicks();</p>
<p>&nbsp;char tmp[32];<br />&nbsp;sprintf(tmp,&quot;dda:%d\nbresham:%d&quot;,t2-t1,t4-t3);<br />&nbsp;MessageBox(NULL,tmp,&quot;Message&quot;,4);</p>
<p><br />&nbsp;bresenham_circle(screen,600,480,100,color);<br />&nbsp;Uint32 color_fill = SDL_MapRGB(screen-&gt;format,0xff,0x00,0x00);<br />&nbsp;//Uint32 gc = get_pixel(screen,501,381);<br />&nbsp;Uint32 boundary_color = SDL_MapRGB(screen-&gt;format,0xff,0xff,0xff);<br />&nbsp;for(i = 500;i&lt;700;i++)<br />&nbsp;&nbsp;for(j = 380;j&lt;580;j++)<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;//&nbsp;Uint32 gc = get_pixel(screen,i,j);<br />&nbsp;&nbsp;&nbsp;seed_filling(screen,i,j,color_fill,boundary_color);<br />&nbsp;&nbsp;}</p>
<p>&nbsp;//seed_filling(screen,500,380,color_fill,boundary_color);<br />&nbsp;done = 0;<br />&nbsp;int x = 100;<br />&nbsp;int y = 100;<br />&nbsp;while (!done)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SDL_Event event;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 检测事件*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (SDL_PollEvent (&amp;event))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (event.type)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case SDL_KEYDOWN:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case SDL_QUIT:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; done = 1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp;case SDL_KEYUP:<br />&nbsp;&nbsp;&nbsp;&nbsp;if(event.key.keysym.sym == SDLK_ESCAPE)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;done = 1;<br />&nbsp;&nbsp;&nbsp;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;//更新屏幕 <br />&nbsp;&nbsp;if( SDL_Flip( screen ) == -1 )<br />&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;return 1;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;}<br />&nbsp;}<br />&nbsp;&nbsp;&nbsp; SDL_Quit();<br />&nbsp;&nbsp;&nbsp; return 0;&nbsp;&nbsp;&nbsp; <br />}</p>
<p>&nbsp;</p>]]></description>
		</item>
		    
		
		<item>
			<title>Linux设备驱动程序设计入门笔记 2</title>
			<link>http://fitren.blog.sohu.com/38626536.html</link>
			<comments>http://fitren.blog.sohu.com/38626536.html#comment</comments>
			<dc:creator>fitren</dc:creator>
			<pubDate>Wed, 21 Mar 2007 13:38:10 +0800</pubDate>
			<category>技术类</category>
			<guid>http://fitren.blog.sohu.com/38626536.html</guid>
			<description><![CDATA[<a href="http://soft.yesky.com/lesson/1/2648001.shtml" target="_blank">http://soft.yesky.com/lesson/1/2648001.shtml</a><br />
<font style="color: rgb(255, 0, 0);" size="5"><span style="font-weight: bold;">阻塞与非阻塞</span></font><br />
<br />
　　阻塞操作是指，在执行设备操作时，若不能获得资源，则进程挂起直到满足可操作的条件再进行操作。非阻塞操作的进程在不能进行设备操作时，并不挂起。被挂起的进程进入sleep状态，被从调度器的运行队列移走，直到等待的条件被满足。<br />
&nbsp;&nbsp; &nbsp;在Linux驱动程序中，我们可以使用等待队列（wait queue）来实现阻塞操作。wait
queue很早就作为一个基本的功能单位出现在Linux内核里了，它以队列为基础数据结构，与进程调度机制紧密结合，能够用于实现核心的异步事件通知机
制。等待队列可以用来同步对系统资源的访问，上节中所讲述Linux信号量在内核中也是由等待队列来实现的。　　<br />
示例：<br /><span style="color: rgb(0, 0, 255);">
#include &lt;linux/module.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
#include &lt;linux/init.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
#include &lt;linux/fs.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
#include &lt;asm/uaccess.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
#include &lt;linux/wait.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
#include &lt;asm/semaphore.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
MODULE_LICENSE(&quot;GPL&quot;);</span><br />
<br /><span style="color: rgb(0, 0, 255);">
#define MAJOR_NUM 254</span><br />
<br /><span style="color: rgb(0, 0, 255);">
static ssize_t globalvar_read(struct file *, char *, size_t, loff_t*);</span><br /><span style="color: rgb(0, 0, 255);">
static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*);</span><br />
<br /><span style="color: rgb(0, 0, 255);">
struct file_operations globalvar_fops =</span><br /><span style="color: rgb(0, 0, 255);">
{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;.read=globalvar_read,</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;.write=globalvar_write,</span><br /><span style="color: rgb(0, 0, 255);">
};</span><br />
<br /><span style="color: rgb(0, 0, 255);">
static int global_var = 0;</span><br /><span style="color: rgb(0, 0, 255);">
static struct semaphore sem;</span><br /><span style="color: rgb(0, 0, 255);">
static wait_queue_head_t outq;</span><br /><span style="color: rgb(0, 0, 255);">
static int flag = 0;</span><br />
<br /><span style="color: rgb(0, 0, 255);">
static int __init globalvar_init(void)</span><br /><span style="color: rgb(0, 0, 255);">
{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;int ret;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;ret = register_chrdev(MAJOR_NUM, &quot;globalvar&quot;, &amp;globalvar_fops);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;if (ret)</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(&quot;globalvar_waitqueue register failure&quot;);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;else</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(&quot;globalvar_waitqueue register success&quot;);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;init_MUTEX(&amp;sem);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;init_waitqueue_head(&amp;outq);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;return ret;</span><br /><span style="color: rgb(0, 0, 255);">
}</span><br />
<br /><span style="color: rgb(0, 0, 255);">
static void __exit globalvar_exit(void)</span><br /><span style="color: rgb(0, 0, 255);">
{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;int ret;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;ret = unregister_chrdev(MAJOR_NUM, &quot;globalvar&quot;);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;if (ret)</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(&quot;globalvar_waitqueue unregister failure&quot;);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;else</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(&quot;globalvar_waitqueue unregister success&quot;);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
}</span><br />
<br /><span style="color: rgb(0, 0, 255);">
static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)</span><br /><span style="color: rgb(0, 0, 255);">
{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;//等待数据可获得</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;if (wait_event_interruptible(outq, flag != 0))</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return - ERESTARTSYS;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br />
<br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;if (down_interruptible(&amp;sem))</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return - ERESTARTSYS;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br />
<br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;flag = 0;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;if (copy_to_user(buf, &amp;global_var, sizeof(int)))</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;up(&amp;sem);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return - EFAULT;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;up(&amp;sem);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;return sizeof(int);</span><br /><span style="color: rgb(0, 0, 255);">
}</span><br />
<br /><span style="color: rgb(0, 0, 255);">
static ssize_t globalvar_write(struct file *filp, const char *buf, size_t len,loff_t *off)</span><br /><span style="color: rgb(0, 0, 255);">
{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;if (down_interruptible(&amp;sem))</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return - ERESTARTSYS;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;if (copy_from_user(&amp;global_var, buf, sizeof(int)))</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;up(&amp;sem);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return - EFAULT;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;up(&amp;sem);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;flag = 1;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;//通知数据可获得</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;wake_up_interruptible(&amp;outq);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;return sizeof(int);</span><br /><span style="color: rgb(0, 0, 255);">
}</span><br />
<br /><span style="color: rgb(0, 0, 255);">
module_init(globalvar_init);</span><br /><span style="color: rgb(0, 0, 255);">
module_exit(globalvar_exit);</span><br />
<br />
写设备/dev/waitqueue<br /><span style="color: rgb(0, 0, 255);">
#include &lt;sys/types.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
#include &lt;sys/stat.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
#include &lt;stdio.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
#include &lt;fcntl.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
main()</span><br /><span style="color: rgb(0, 0, 255);">
{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;int fd, num;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;fd = open(&quot;/dev/waitqueue&quot;, O_RDWR, S_IRUSR | S_IWUSR);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;if (fd != - 1)</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;while (1)</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf(&quot;Please input the globalvar:\n&quot;);</span><br />
&nbsp;<span style="color: rgb(0, 0, 255);">&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;scanf(&quot;%d&quot;, &amp;num);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;write(fd, &amp;num, sizeof(int));&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//如果输入是0，则退出</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (num == 0)</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;close(fd);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;else</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf(&quot;device open failure\n&quot;);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
}</span><br />
<br />
读设备：<br /><span style="color: rgb(0, 0, 255);">
#include &lt;sys/types.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
#include &lt;sys/stat.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
#include &lt;stdio.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
#include &lt;fcntl.h&gt;</span><br /><span style="color: rgb(0, 0, 255);">
main()</span><br /><span style="color: rgb(0, 0, 255);">
{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;int fd, num;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;fd = open(&quot;/dev/waitqueue&quot;, O_RDWR, S_IRUSR | S_IWUSR);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;if (fd != - 1)</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;while (1)</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;read(fd, &amp;num, sizeof(int)); //程序将阻塞在此语句，除非有针对globalvar的输入</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf(&quot;The globalvar is %d\n&quot;, num);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//如果输入是0，则退出</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (num == 0)</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;close(fd);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;else</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;{</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf(&quot;device open failure\n&quot;);</span><br /><span style="color: rgb(0, 0, 255);">
&nbsp;&nbsp; &nbsp;}</span><br /><span style="color: rgb(0, 0, 255);">
}</span><br />
<br />
打开两个终端，分别运行上述两个应用程序，发现当在第二个终端中没有输入数据时，第一个终端没有输出（阻塞），每当我们在第二个终端中给globalvar输入一个值，第一个终端就会输出这个值，<br />
./write<br />
Please input the globalvar:<br />
2<br />
Please input the globalvar:<br />
3<br />
Please input the globalvar:<br />
<br />
./read<br />
The globalvar is 2<br />
The globalvar is 3]]></description>
		</item>
		    
		
		<item>
			<title>Linux设备驱动程序设计入门 笔记1</title>
			<link>http://fitren.blog.sohu.com/38619076.html</link>
			<comments>http://fitren.blog.sohu.com/38619076.html#comment</comments>
			<dc:creator>fitren</dc:creator>
			<pubDate>Mon, 26 Mar 2007 10:54:01 +0800</pubDate>
			<category>技术类</category>
			<guid>http://fitren.blog.sohu.com/38619076.html</guid>
			<description><![CDATA[<a href="http://soft.yesky.com/lesson/1/2648001.shtml" target="_blank">http://soft.yesky.com/lesson/1/2648001.shtml</a><br /><br /><font style="FONT-WEIGHT: bold; COLOR: rgb(255,0,0)" size="5">内核模块</font><br />Linux内核的一个模块可以以两种方式被编译和加载：<br />　　（1）直接编译进Linux内核，随同Linux启动时加载；<br />　　（2）编译成一个可加载和删除的模块，使用insmod加载（modprobe和insmod命令类似，但依赖于相关的配置文件），rmmod删除。这种方式控制了内核的大小，而模块一旦被插入内核，它就和内核其他部分一样。<br /><br />示例：<br /><span style="COLOR: rgb(0,0,255)">#include &lt;linux/init.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;linux/module.h&gt;//所有模块都需要的头文件</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;linux/kernel.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">#ifndef __KERNEL__</span><br /><span style="COLOR: rgb(0,0,255)">#define __KERNEL__</span><br /><span style="COLOR: rgb(0,0,255)">#endif</span><br /><span style="COLOR: rgb(0,0,255)">#ifndef MODULE</span><br /><span style="COLOR: rgb(0,0,255)">#define MODULE</span><br /><span style="COLOR: rgb(0,0,255)">#endif</span><br /><span style="COLOR: rgb(0,0,255)">static int hello_init(void)</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;printk(KERN_EMERG&quot;Hello,world!\n&quot;);//KERN_EMERG：在插入模块时，在终端打印出信息;KERN_ALERT:在log(/var/log/messages)中显示信息</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;char* buf;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;buf=kmalloc(100,GFP_KERNEL);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;char* buf1;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;buf1=&quot;This is the hello init!&quot;;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;strcpy(buf,buf1);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;printk(&quot;%s\n&quot;,buf);&nbsp;&nbsp; &nbsp;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;kfree(buf);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;return 0;</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><br /><span style="COLOR: rgb(0,0,255)">static void hello_exit(void)</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;int i=0;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;for(i=0;i&lt;5;i++)</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(KERN_EMERG&quot;%d\n&quot;,i);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;printk(KERN_EMERG&quot;Bye!\n&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><br /><span style="COLOR: rgb(0,0,255)">module_init(hello_init);</span><br /><span style="COLOR: rgb(0,0,255)">module_exit(hello_exit);</span><br /><br /><span style="COLOR: rgb(0,0,255)">MODULE_LICENSE(&quot;GPL&quot;);</span><br /><br />Makefile:<br /><span style="COLOR: rgb(51,0,255)">OBJ=hello.o</span><br /><span style="COLOR: rgb(51,0,255)">PROG=hello.ko</span><br /><span style="COLOR: rgb(51,0,255)">obj-m := $(OBJ)</span><br /><span style="COLOR: rgb(51,0,255)">KERNELBUILD := /lib/modules/`uname -r`/build</span><br /><span style="COLOR: rgb(51,0,255)">default:</span><br /><span style="COLOR: rgb(51,0,255)">&nbsp;&nbsp; &nbsp;make -C $(KERNELBUILD) M=$(shell pwd) modules</span><br /><span style="COLOR: rgb(51,0,255)">clean:</span><br /><span style="COLOR: rgb(255,255,0)"><span style="COLOR: rgb(51,0,255)">&nbsp;&nbsp; &nbsp;rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions *</span>~</span><br />&nbsp;&nbsp; &nbsp;<br />加载hello.ko模块：insmod hello.ko，就会在终端有输出<br />卸载hello.ko模块：rmmod hello.ko<br /><br /><font size="5"><span style="COLOR: rgb(255,0,0)">字符设备驱动程序</span></font><br /><br />Linux主要将设备分为二类：字符设备和块设备。字符设备是指设备发送和接收数据以字符的形式进行；而块设备则以整个数据缓冲区的形式进行。字符设备的驱动相对比较简单。<br /><br />示例：<br /><span style="COLOR: rgb(0,0,255)">//mknod /dev/globalvar c 254 0 建立设备接点，必须与注册的设备号相同</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;linux/module.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;linux/init.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;linux/fs.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;asm/uaccess.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">MODULE_LICENSE(&quot;GPL&quot;);</span><br /><br /><span style="COLOR: rgb(0,0,255)">#define MAJOR_NUM 254 //主设备号</span><br /><span style="COLOR: rgb(0,0,255)">static ssize_t globalvar_read(struct file *, char *, size_t, loff_t*);</span><br /><span style="COLOR: rgb(0,0,255)">static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*);</span><br /><br /><span style="COLOR: rgb(0,0,255)">int globalvar_var=1;</span><br /><br /><span style="COLOR: rgb(0,0,255)">static struct file_operations globalvar_fops={</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;.read = globalvar_read,</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;.write = globalvar_write,//如果把这里注释，那么设备/dev/globalvar就没有可写的权限</span><br /><span style="COLOR: rgb(0,0,255)">};</span><br />/*<font style="COLOR: rgb(0,0,255)"> <pre>    struct file_operations {<br />       struct module *owner;<br />       loff_t (*llseek) (struct file *, loff_t, int);<br />       ssize_t (*read) (struct file *, char *, size_t, loff_t *);<br />       ssize_t (*write) (struct file *, const char *, size_t, loff_t *);<br />       int (*readdir) (struct file *, void *, filldir_t);<br />       unsigned int (*poll) (struct file *, struct poll_table_struct *);<br />       int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);<br />       int (*mmap) (struct file *, struct vm_area_struct *);<br />       int (*open) (struct inode *, struct file *);<br />       int (*flush) (struct file *);<br />       int (*release) (struct inode *, struct file *);<br />       int (*fsync) (struct file *, struct dentry *, int datasync);<br />       int (*fasync) (int, struct file *, int);<br />       int (*lock) (struct file *, int, struct file_lock *);<br />    	 ssize_t (*readv) (struct file *, const struct iovec *, unsigned long,<br />          loff_t *);<br />    	 ssize_t (*writev) (struct file *, const struct iovec *, unsigned long,<br />          loff_t *);<br />    };</pre></font>
<p><br />&nbsp;</p>
<p><span style="COLOR: rgb(0,0,255)"></span><font color="#0000ff">struct file {<br />&nbsp; mode_t f_mode;<br />&nbsp; loff_t f_pos;<br />&nbsp; unsigned short f_flags;<br />&nbsp; unsigned short f_count;<br />&nbsp; unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;<br />&nbsp; struct file *f_next, *f_prev;<br />&nbsp; int f_owner;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* pid or -pgrp where SIGIO should be sent */<br />&nbsp; struct inode * f_inode;<br />&nbsp; struct file_operations * f_op;<br />&nbsp; unsigned long f_version;<br />&nbsp; void *private_data;&nbsp; /* needed for tty driver, and maybe others */<br />};</font><span style="COLOR: rgb(0,0,255)"><font color="#000000">*/</font></span><br /><br /><span style="COLOR: rgb(0,0,255)">static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;//globalvar_var从内核空间复制到用户空间</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;if (copy_to_user(buf, &amp;globalvar_var, sizeof(int)))</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return - EFAULT;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;return sizeof(int);</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><br /><span style="COLOR: rgb(0,0,255)">static ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;//将用户空间的数据复制到内核空间的global_var</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;if (copy_from_user(&amp;globalvar_var, buf, sizeof(int)))</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return - EFAULT;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;return sizeof(int);</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><span style="COLOR: rgb(0,0,255)">static int globalvar_init(void)</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;int ret;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;ret=register_chrdev(MAJOR_NUM,&quot;globalvar&quot;,&amp;globalvar_fops);//注册字符设备</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;if(ret)</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(&quot;globalvar register failure!\n&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;else</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(&quot;globalvar register success\n&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;return 0;</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><span style="COLOR: rgb(0,0,255)">void globalvar_exit(void)</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;int ret=unregister_chrdev(MAJOR_NUM,&quot;globalvar&quot;);//注消字符设备</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;if (ret)</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{&nbsp;&nbsp; &nbsp;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(&quot;globalvar unregister failure\n&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;else</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(&quot;globalvar unregister success\n&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><span style="COLOR: rgb(0,0,255)">module_init(globalvar_init);</span><br /><span style="COLOR: rgb(0,0,255)">module_exit(globalvar_exit);</span><br /><br /><span style="COLOR: rgb(0,0,0)">写一个应用态的程序来打开字符设备文件:/dev/globalvar</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;sys/types.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;sys/stat.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;stdio.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;fcntl.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">int main()</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;int fd, num;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;fd = open(&quot;/dev/globalvar&quot;, O_RDWR, S_IRUSR | S_IWUSR);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;if (fd != -1 )</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;read(fd, &amp;num, sizeof(int));</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf(&quot;The globalvar is %d\n&quot;, num);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf(&quot;Please input the num written to globalvar\n&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;scanf(&quot;%d&quot;, &amp;num);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;int ret=write(fd, &amp;num, sizeof(int));</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if(ret==-1)</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf(&quot;Can not write file :/dev/globalvar!\n&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;read(fd, &amp;num, sizeof(int));</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf(&quot;The globalvar is %d\n&quot;, num);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;close(fd);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;else</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printf(&quot;Device open failure\n&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;return 0;</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><br />编译后运行结果：The globalvar is 0<br />Please input the num written to globalvar<br /><br /><br /><font style="FONT-WEIGHT: bold; COLOR: rgb(255,0,0)" size="5">并发控制</font><br /><br />在驱动程序中，当多个线程同时访问相同的资源时（驱动程序中的全局变量是一种典型的共享资源），可能会引发&quot;竞态&quot;，因此我们必须对共享资源进行并发控制。Linux内核中解决并发控制的最常用方法是自旋锁与信号量（绝大多数时候作为互斥锁使用）。<br />　　自旋锁与信号量&quot;类似而不类&quot;，类似说的是它们功能上的相似性，&quot;不类&quot;指代它们在本质和实现机理上完全不一样，不属于一类。<br />　　自旋锁不会引起调用者睡眠，如果自旋锁已经被别的执行单元保持，调用者就一直循环查看是否该自旋锁的保持者已经释放了锁，&quot;自旋&quot;就是&quot;在原地打转&quot;。而信号量则引起调用者睡眠，它把进程从运行队列上拖出去，除非获得锁。这就是它们的&quot;不类&quot;。<br />　　但是，无论是信号量，还是自旋锁，在任何时刻，最多只能有一个保持者，即在任何时刻最多只能有一个执行单元获得锁。这就是它们的&quot;类似&quot;。<br />　　鉴于自旋锁与信号量的上述特点，一般而言，自旋锁适合于保持时间非常短的情况，它可以在任何上下文使用；信号量适合于保持时间较长的情况，会只能在进程上下文使用。如果被保护的共享资源只在进程上下文访问，则可以以信号量来保护该共享资源，如果对共享资源的访问时间非常短，自旋锁也是好的选择。但是，如果被保护的共享资源需要在中断上下文访问（包括底半部即中断处理句柄和顶半部即软中断），就必须使用自旋锁。<br /><br />示例<br /><span style="COLOR: rgb(0,0,255)">//mknod /dev/spin c 254 0</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;linux/module.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;linux/init.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;linux/fs.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;asm/uaccess.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">#include &lt;asm/semaphore.h&gt;</span><br /><span style="COLOR: rgb(0,0,255)">MODULE_LICENSE(&quot;GPL&quot;);</span><br /><br /><span style="COLOR: rgb(0,0,255)">#define MAJOR_NUM 254</span><br /><br /><span style="COLOR: rgb(0,0,255)">static ssize_t globalvar_read(struct file *, char *, size_t, loff_t*);</span><br /><span style="COLOR: rgb(0,0,255)">static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*);</span><br /><span style="COLOR: rgb(0,0,255)">static int globalvar_open(struct inode *inode, struct file *filp);</span><br /><span style="COLOR: rgb(0,0,255)">static int globalvar_release(struct inode *inode, struct file *filp);</span><br /><br /><span style="COLOR: rgb(0,0,255)">struct file_operations globalvar_fops =</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;.read= globalvar_read,</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;.write=globalvar_write,</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;.open=globalvar_open,</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;.release=globalvar_release,&nbsp;&nbsp; &nbsp;</span><br /><span style="COLOR: rgb(0,0,255)">};</span><br /><br /><span style="COLOR: rgb(0,0,255)">static int global_var = 0;</span><br /><span style="COLOR: rgb(0,0,255)">static int globalvar_count = 0;</span><br /><span style="COLOR: rgb(0,0,255)">static struct semaphore sem;</span><br /><span style="COLOR: rgb(0,0,255)">static spinlock_t spin = SPIN_LOCK_UNLOCKED;</span><br /><br /><span style="COLOR: rgb(0,0,255)">static int __init globalvar_init(void)</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;int ret;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;ret = register_chrdev(MAJOR_NUM, &quot;globalvar&quot;, &amp;globalvar_fops);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;if (ret)</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(&quot;globalvar register failure&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;else</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(&quot;globalvar register success&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;init_MUTEX(&amp;sem);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;return ret;</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><br /><span style="COLOR: rgb(0,0,255)">static void __exit globalvar_exit(void)</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;int ret;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;ret = unregister_chrdev(MAJOR_NUM, &quot;globalvar&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;if (ret)</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(&quot;globalvar unregister failure&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;else</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(&quot;globalvar unregister success&quot;);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><br /><span style="COLOR: rgb(0,0,255)">static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;//获得信号量</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;if (down_interruptible(&amp;sem))</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return - ERESTARTSYS;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}&nbsp;&nbsp; &nbsp;</span><br /><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;//将global_var从内核空间复制到用户空间</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;if (copy_to_user(buf, &amp;global_var, sizeof(int)))</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;up(&amp;sem);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return - EFAULT;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;//释放信号量</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;up(&amp;sem);</span><br /><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;return sizeof(int);</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><br /><span style="COLOR: rgb(0,0,255)">ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;//获得信号量</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;if (down_interruptible(&amp;sem))</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return - ERESTARTSYS;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;//将用户空间的数据复制到内核空间的global_var</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;if (copy_from_user(&amp;global_var, buf, sizeof(int)))</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;up(&amp;sem);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return - EFAULT;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;//释放信号量</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;up(&amp;sem);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;return sizeof(int);</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><span style="COLOR: rgb(0,0,255)">static int globalvar_open(struct inode *inode, struct file *filp)</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;//获得自旋锁</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;spin_lock(&amp;spin);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;//临界资源访问</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;if (globalvar_count)</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;spin_unlock(&amp;spin);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return - EBUSY;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;}</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;globalvar_count++;</span><br /><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;//释放自旋锁</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;spin_unlock(&amp;spin);</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;return 0;</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><br /><span style="COLOR: rgb(0,0,255)">static int globalvar_release(struct inode *inode, struct file *filp)</span><br /><span style="COLOR: rgb(0,0,255)">{</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;globalvar_count--;</span><br /><span style="COLOR: rgb(0,0,255)">&nbsp;&nbsp; &nbsp;return 0;</span><br /><span style="COLOR: rgb(0,0,255)">}</span><br /><span style="COLOR: rgb(0,0,255)">module_init(globalvar_init);</span><br /><span style="COLOR: rgb(0,0,255)">module_exit(globalvar_exit);</span><br /><br />用上面的应用示例来测试，分别两个终端打开相同的字符设备文件：/dev/spin，此时得到的结果不同：<br />1：./testspin<br />The globalvar is 0<br />Please input the num written to globalvar<br />2：./testspin<br />Device open failure<br /><br />表明前面的进程还没有释放，后面的进程就不能打开<br /><br /></p>]]></description>
		</item>
		    
		
		<item>
			<title>《linux编程宝典》笔记4</title>
			<link>http://fitren.blog.sohu.com/37400921.html</link>
			<comments>http://fitren.blog.sohu.com/37400921.html#comment</comments>
			<dc:creator>fitren</dc:creator>
			<pubDate>Wed, 21 Mar 2007 10:58:31 +0800</pubDate>
			<category>技术类</category>
			<guid>http://fitren.blog.sohu.com/37400921.html</guid>
			<description><![CDATA[信号　　　值　　处理动作　发出信号的原因 <br />
<br />
---------------------------------------------------------------------- <br />
<br />
SIGHUP 1　　　 　A　　终端挂起或者控制进程终止<br />
<br />
&nbsp;SIGINT 2　　　 　A　　键盘中断（如break键被按下）<br />
<br />
&nbsp;SIGQUIT 3　　 　 C　　键盘的退出键被按下<br />
<br />
&nbsp;SIGILL 4　　 　　C　　非法指令<br />
<br />
&nbsp;SIGABRT 6　　　　 C　　由abort(3)发出的退出指令<br />
<br />
&nbsp;SIGFPE 8　　　　 C　　浮点异常<br />
<br />
&nbsp;SIGKILL 9　　 　 AEF　 Kill信号<br />
<br />
&nbsp;SIGSEGV 11　　 　 C　　无效的内存引用<br />
<br />
&nbsp;SIGPIPE 13　　 　 A　　管道破裂: 写一个没有读端口的管道<br />
<br />
&nbsp;SIGALRM 14　　　 A　　由alarm(2)发出的信号<br />
<br />
&nbsp;SIGTERM 15　　　 A　　终止信号<br />
<br />
&nbsp;SIGUSR1 30,10,16 A　　用户自定义信号1<br />
<br />
&nbsp;SIGUSR2 31,12,17 A　　用户自定义信号2<br />
<br />
&nbsp;SIGCHLD 20,17,18 B　　子进程结束信号<br />
<br />
&nbsp;SIGCONT 19,18,25 　　　进程继续（曾被停止的进程）<br />
<br />
&nbsp;SIGSTOP 17,19,23 DEF　终止进程<br />
<br />
&nbsp;SIGTSTP 18,20,24 D　　控制终端（tty）上按下停止键<br />
<br />
&nbsp;SIGTTIN 21,21,26 D　　后台进程企图从控制终端读<br />
<br />
&nbsp;SIGTTOU 22,22,27 D　　后台进程企图从控制终端写 <br />
<br />
　　下面的信号没在POSIX.1中列出，而在SUSv2列出<br />
<br />
信号　　　 值　 　处理动作　发出信号的原因<br />
<br />
&nbsp;--------------------------------------------------------------------<br />
<br />
&nbsp;SIGBUS 10,7,10 C 总线错误(错误的内存访问)<br />
<br />
&nbsp;SIGPOLL A Sys V定义的Pollable事件，与SIGIO同义<br />
<br />
&nbsp;SIGPROF 27,27,29 A Profiling定时器到<br />
<br />
&nbsp;SIGSYS 12,-,12 C 无效的系统调用 (SVID)<br />
<br />
&nbsp;SIGTRAP 5 C 跟踪/断点捕获<br />
<br />
&nbsp;SIGURG 16,23,21 B Socket出现紧急条件(4.2 BSD)<br />
<br />
&nbsp;SIGVTALRM 26,26,28 A 实际时间报警时钟信号(4.2 BSD)<br />
<br />
&nbsp;SIGXCPU 24,24,30 C 超出设定的CPU时间限制(4.2 BSD)<br />
<br />
&nbsp;SIGXFSZ 25,25,31 C 超出设定的文件大小限制(4.2 BSD) <br />
<br />
（对于SIGSYS，SIGXCPU，SIGXFSZ，以及某些机器体系结构下的SIGBUS，Linux缺省的动作是A (terminate)，SUSv2 是C (terminate and dump core)）。<br />
<br />
　　下面是其它的一些信号:<br />
<br />
信号　　　 值　 　处理动作　发出信号的原因<br />
<br />
&nbsp;---------------------------------------------------------------------- <br />
<br />
SIGIOT 6 C IO捕获指令，与SIGABRT同义<br />
<br />
&nbsp;SIGEMT 7,-,7 SIGSTKFLT -,16,- A 协处理器堆栈错误<br />
<br />
&nbsp;SIGIO 23,29,22 A 某I/O操作现在可以进行了(4.2 BSD)<br />
<br />
&nbsp;SIGCLD -,-,18 A 与SIGCHLD同义<br />
<br />
&nbsp;SIGPWR 29,30,19 A 电源故障(System V)<br />
<br />
&nbsp;SIGINFO 29,-,- A 与SIGPWR同义<br />
<br />
&nbsp;SIGLOST -,-,- A 文件锁丢失<br />
<br />
&nbsp;SIGWINCH 28,28,20 B 窗口大小改变(4.3 BSD, Sun)<br />
<br />
&nbsp;SIGUNUSED -,31,- A 未使用的信号(will be SIGSYS) <br />
<br />
（在这里，- 表示信号没有实现；有三个值给出的含义为，第一个值通常在Alpha和Sparc上有效，中间的值对应i386和ppc以及sh，最后一个值对应mips。信号29在Alpha上为SIGINFO / SIGPWR ，在Sparc上为SIGLOST。）<br />
<br />
　　处理动作一项中的字母含义如下:<br />
<br />
&nbsp;&nbsp;&nbsp; * A 缺省的动作是终止进程<br />
&nbsp;&nbsp;&nbsp; * B 缺省的动作是忽略此信号<br />
&nbsp;&nbsp;&nbsp; * C 缺省的动作是终止进程并进行内核映像转储（dump core）<br />
&nbsp;&nbsp;&nbsp; * D 缺省的动作是停止进程<br />
&nbsp;&nbsp;&nbsp; * E 信号不能被捕获<br />
&nbsp;&nbsp;&nbsp; * F 信号不能被忽略 <br />
<br />
　　上面介绍的信号是常见系统所支持的。以表格的形式介绍了各种信号的名称、作用及其在默认情况下的处理动作。各种默认处理动作的含义是：终止程序是指进
程退出；忽略该信号是将该信号丢弃，不做处理；停止程序是指程序挂起，进入停止状况以后还能重新进行下去，一般是在调试的过程中（例如ptrace系统调
用）；内核映像转储是指将进程数据在内存的映像和进程在内核结构中存储的部分内容以一定格式转储到文件系统，并且进程退出执行，这样做的好处是为程序员提
供了方便，使得他们可以得到进程当时执行时的数据值，允许他们确定转储的原因，并且可以调试他们的程序。<br />
<br />
　　注意: 信号SIGKILL和SIGSTOP既不能被捕捉，也不能被忽略。信号SIGIOT与SIGABRT是一个信号。可以看出，同一个信号在不同的系统中值可能不一样，所以建议最好使用为信号定义的名字，而不要直接使用信号的值。<br />
<br />
具体实例：<br />
1.alarm唤醒<br />
#include &lt;unistd.h&gt;<br />
#include &lt;signal.h&gt;<br />
#include &lt;stdio.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
void handler()<br />
{<br />
&nbsp;&nbsp;&nbsp; printf(&quot;hello\n&quot;);<br />
//&nbsp;&nbsp;&nbsp; _exit(0);<br />
}<br />
int main()<br />
{<br />
&nbsp;&nbsp;&nbsp; int i;<br />
&nbsp;&nbsp;&nbsp; signal(SIGALRM,handler);<br />
&nbsp;&nbsp;&nbsp; alarm(2);<br />
&nbsp;&nbsp;&nbsp; for(i=1;i&lt;4;i++)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;sleep %d ...\n&quot;,i);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sleep(1);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return 0;<br />
}<br />
2.pause来暂停执行，直到有信号来唤醒<br />
#include &lt;signal.h&gt;<br />
#include &lt;stdio.h&gt;<br />
#include &lt;unistd.h&gt;<br />
void sigroutine(int signum)<br />
{<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Caught signal SIGINT!\n&quot;);<br />
}<br />
int main()<br />
{<br />
//&nbsp;&nbsp;&nbsp; signal(SIGTERM,&amp;sigroutine);//在终端输入killall pause时，signal捕捉到信号<br />
&nbsp;&nbsp;&nbsp; signal(SIGINT,&amp;sigroutine);//在终端按下CTL+C时，signal捕捉到信号<br />
&nbsp;&nbsp;&nbsp; pause();<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Continue!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; return 0;<br />
}<br />
<br />
3.多个信号的处理<br />
#include &lt;stdio.h&gt;<br />
#include &lt;signal.h&gt;<br />
#include &lt;time.h&gt;<br />
#include &lt;unistd.h&gt;<br />
#include &lt;sys/types.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
#include &lt;string.h&gt;<br />
<br />
void sighandler(int signum);<br />
void continuehandler(int signum);<br />
char buffer[200];<br />
<br />
int main()<br />
{<br />
&nbsp;&nbsp;&nbsp; strcpy(buffer,&quot;None\n&quot;);<br />
&nbsp;&nbsp;&nbsp; if(signal(SIGTERM,&amp;sighandler)==SIG_ERR)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Can not register signal SIGTERM!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if(signal(SIGINT,&amp;sighandler)==SIG_ERR)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Can not register signal SIGINT!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if(signal(SIGCONT,&amp;continuehandler)==SIG_ERR)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Can not register signal SIGCONT!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; while(1)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fgets(buffer,sizeof(buffer),stdin);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Input:%s&quot;,buffer);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return 0;<br />
}<br />
void sighandler(int signum)<br />
{<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Caught signal %d.\n&quot;,signum);<br />
//&nbsp;&nbsp;&nbsp; _exit(0);<br />
}<br />
void continuehandler(int signum)<br />
{<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Continuing!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Your last input was:%s&quot;,buffer);<br />
}<br />
/*<br />
[root@fitren signal]# ./signal2<br />
hello world<br />
Input:hello world<br />
Caught signal 2.#ctl+c<br />
Caught signal 15.#这里是另外开一个端，killall signal2<br />
<br />
[root@fitren signal]# ./signal2 &amp;<br />
[1] 31993<br />
[root@fitren signal]#<br />
<br />
[1]+&nbsp; Stopped&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ./signal2<br />
[root@fitren signal]# fg<br />
./signal2<br />
Continuing!<br />
Your last input was:None#后台运行之后，再前台运行，这样就触发信号SIGCONT<br />
*/<br />
<br />
4.两个程序间的通讯<br />
service.c<br />
<br />
#include &lt;stdio.h&gt;<br />
#include &lt;signal.h&gt;<br />
void sigroutine(int signum)<br />
{<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Hello,I received a signal from client!\n&quot;);<br />
}<br />
int main()<br />
{<br />
&nbsp;&nbsp;&nbsp; for(;;)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; signal(SIGTERM,&amp;sigroutine);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pause();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return 0;&nbsp;&nbsp;&nbsp; <br />
}<br />
<br />
<br />
clients.c<br />
<br />
#include &lt;stdio.h&gt;<br />
#include &lt;signal.h&gt;<br />
#include &lt;sys/types.h&gt;<br />
int main()<br />
{<br />
&nbsp;&nbsp;&nbsp; kill(31485,SIGTERM);<br />
&nbsp;&nbsp;&nbsp; return 0;&nbsp;&nbsp;&nbsp; <br />
}<br />
5.阻塞信号示例<br />
#include &lt;stdio.h&gt;<br />
#include &lt;signal.h&gt;<br />
#include &lt;time.h&gt;<br />
#include &lt;unistd.h&gt;<br />
#include &lt;sys/types.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
#include &lt;string.h&gt;<br />
<br />
void sighandler(int signum);<br />
void continuehandler(int signum);<br />
char buffer[200];<br />
<br />
int main()<br />
{<br />
&nbsp;&nbsp;&nbsp; sigset_t blockset;//声明一个sigset_t类型的变量，这种数据类型是基本的信号集，它包含了一系列的信号<br />
&nbsp;&nbsp;&nbsp; strcpy(buffer,&quot;None\n&quot;);<br />
&nbsp;&nbsp;&nbsp; if(signal(SIGTERM,&amp;sighandler)==SIG_ERR)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Can not register signal SIGTERM!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if(signal(SIGINT,&amp;sighandler)==SIG_ERR)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Can not register signal SIGINT!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if(signal(SIGCONT,&amp;continuehandler)==SIG_ERR)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Can not register signal SIGCONT!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; sigemptyset(&amp;blockset);//初始化为空集<br />
&nbsp;&nbsp;&nbsp; sigaddset(&amp;blockset,SIGTERM);//将信号SIGTERM和SIGINT添加到信号集中<br />
&nbsp;&nbsp;&nbsp; sigaddset(&amp;blockset,SIGINT);<br />
&nbsp;&nbsp;&nbsp; while(1)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sigprocmask(SIG_BLOCK,&amp;blockset,NULL);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fgets(buffer,sizeof(buffer),stdin);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Input:%s&quot;,buffer);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*计算挂起信号的个数<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sigset_t pending;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int pendingcount=0;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sigpending(&amp;pending);//填充一个信号集就像前面的手工创建一个信号集一样<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(sigismember(&amp;pending,SIGINT)) pendingcount++;//计算SIGINT和SIGTERM信号出现的个数<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(sigismember(&amp;pending,SIGTERM)) pendingcount++;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;There are %d signals pending.\n&quot;,pendingcount);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sigprocmask(SIG_UNBLOCK,&amp;blockset,NULL);//如果在前面有任何信号悬挂而未被处理，它们都将被处理<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return 0;<br />
}<br />
void sighandler(int signum)<br />
{<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Caught signal %d.\n&quot;,signum);<br />
//&nbsp;&nbsp;&nbsp; _exit(0);<br />
}<br />
void continuehandler(int signum)<br />
{<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Continuing!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Your last input was:%s&quot;,buffer);<br />
}<br />
/*[root@fitren signal]# ./signal3<br />
I am sending CTL+C in the middle of the line#在这句话的中间加入CTL+C中断信号，而等待用户输入完毕之后，这个信号才触发，并只显示后面一半的信息<br />
Input:in the middle of the line<br />
Caught signal 2.<br />
I am sending SIGSTOP at the end of the line CTL+Z#在这个地方按下CTL+Z使程序后台挂起<br />
[1]+&nbsp; Stopped&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ./signal3<br />
[root@fitren signal]# fg<br />
./signal3<br />
Continuing!<br />
Your last input was:in the middle of the line<br />
another line<br />
Input:another line*/<br />
//使用sigation示例<br />
#include &lt;stdio.h&gt;<br />
#include &lt;signal.h&gt;<br />
#include &lt;time.h&gt;<br />
#include &lt;unistd.h&gt;<br />
#include &lt;sys/types.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
#include &lt;string.h&gt;<br />
<br />
#if defined(__linux__) &amp;&amp; ! defined(SL_KERNEL)<br />
#define SL_KERNEL 0x80<br />
#endif<br />
<br />
<br />
void sighandler(int signum,siginfo_t *info,void *extra);<br />
void continuehandler(int signum,siginfo_t *info,void *extra);<br />
char buffer[200];<br />
<br />
int main()<br />
{<br />
&nbsp;&nbsp;&nbsp; struct sigaction act;<br />
&nbsp;&nbsp;&nbsp; sigset_t blockset,pending;<br />
&nbsp;&nbsp;&nbsp; int pendingcount;<br />
&nbsp;&nbsp;&nbsp; strcpy(buffer,&quot;None\n&quot;);<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; sigemptyset(&amp;blockset);<br />
&nbsp;&nbsp;&nbsp; act.sa_mask=blockset;<br />
&nbsp;&nbsp;&nbsp; act.sa_flags=SA_SIGINFO;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; act.sa_sigaction=&amp;sighandler;//两个信号共用一个信号处理函数<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if(sigaction(SIGTERM,&amp;act,NULL)==-1)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Can not register signal SIGTERM!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if(sigaction(SIGINT,&amp;act,NULL)==-1)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Can not register signal SIGINT!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; act.sa_sigaction=&amp;continuehandler;<br />
&nbsp;&nbsp;&nbsp; if(sigaction(SIGCONT,&amp;act,NULL)==-1)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Can not register signal SIGCONT!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; sigemptyset(&amp;blockset);//初始化为空集<br />
&nbsp;&nbsp;&nbsp; sigaddset(&amp;blockset,SIGTERM);//将信号SIGTERM和SIGINT添加到信号集中<br />
&nbsp;&nbsp;&nbsp; sigaddset(&amp;blockset,SIGINT);<br />
&nbsp;&nbsp;&nbsp; while(1)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sigprocmask(SIG_BLOCK,&amp;blockset,NULL);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fgets(buffer,sizeof(buffer),stdin);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Input:%s&quot;,buffer);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*计算挂起信号的个数<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sigset_t pending;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int pendingcount=0;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sigpending(&amp;pending);//填充一个信号集就像前面的手工创建一个信号集一样<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(sigismember(&amp;pending,SIGINT)) pendingcount++;//计算SIGINT和SIGTERM信号出现的个数<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(sigismember(&amp;pending,SIGTERM)) pendingcount++;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;There are %d signals pending.\n&quot;,pendingcount);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sigprocmask(SIG_UNBLOCK,&amp;blockset,NULL);//如果在前面有任何信号悬挂而未被处理，它们都将被处理<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return 0;&nbsp;&nbsp;&nbsp; <br />
}<br />
void sighandler(int signum,siginfo_t *info,void *extra)<br />
{<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Caught signal %d.\n&quot;,signum);<br />
//&nbsp;&nbsp;&nbsp; _exit(0);<br />
}<br />
void continuehandler(int signum,siginfo_t *info,void *extra)<br />
{<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Continuing!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Your last input was:%s&quot;,buffer);<br />
}<br />
//执行之后和执行signal3是一样的结果<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct sigaction {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void (*sa_handler)(int);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
void (*sa_sigaction)(int, siginfo_t *, void *);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sigset_t sa_mask;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int sa_flags;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
void (*sa_restorer)(void);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
<br />
sa_flags:标志及其含义:<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; SA_NOCLDSTOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
If&nbsp; signum&nbsp; is&nbsp; SIGCHLD, do not receive notification when<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
child processes stop (i.e., when child processes&nbsp; receive<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
one of SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU).<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SA_ONESHOT or SA_RESETHAND<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Restore&nbsp; the&nbsp; signal action to the default state once the<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
signal handler has been called.<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SA_ONSTACK<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Call the signal handler on an alternate signal stack pro-<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
vided&nbsp; by&nbsp; sigaltstack(2).&nbsp;&nbsp; If an alternate stack
is not<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
available, the default stack will be used.<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SA_RESTART<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Provide behaviour compatible with BSD signal semantics by<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
making certain system calls restartable across signals.<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SA_NOMASK or SA_NODEFER<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Do not prevent the signal from being received from within<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; its own signal handler.<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SA_SIGINFO<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
The signal handler takes 3 arguments, not one.&nbsp;&nbsp; In&nbsp; this<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
case,&nbsp; sa_sigaction&nbsp; should be set instead of sa_handler.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(The sa_sigaction field was added in Linux 2.1.86.)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; siginfo_t {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; si_signo;&nbsp; /* Signal number */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; si_errno;&nbsp; /* An errno value */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; si_code;&nbsp;&nbsp; /* Signal code */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
pid_t&nbsp;&nbsp;&nbsp; si_pid;&nbsp;&nbsp;&nbsp; /* Sending process ID
*/<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
uid_t&nbsp;&nbsp;&nbsp; si_uid;&nbsp;&nbsp;&nbsp; /* Real user ID of
sending process */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; si_status; /* Exit value or signal */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
clock_t&nbsp; si_utime;&nbsp; /* User time consumed */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
clock_t&nbsp; si_stime;&nbsp; /* System time consumed */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sigval_t si_value;&nbsp; /* Signal value */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; si_int;&nbsp;&nbsp;&nbsp; /* POSIX.1b
signal */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
void *&nbsp;&nbsp; si_ptr;&nbsp;&nbsp;&nbsp; /* POSIX.1b signal */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
void *&nbsp;&nbsp; si_addr;&nbsp;&nbsp; /* Memory location which caused
fault */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; si_band;&nbsp;&nbsp; /* Band event */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; si_fd;&nbsp;&nbsp;&nbsp;&nbsp; /*
File descriptor */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
参考sigaction的man page<br />
<br />
申请和释放信号量：<br />
#include &lt;stdio.h&gt;<br />
#include &lt;sys/types.h&gt;<br />
#include &lt;sys/ipc.h&gt;<br />
#include &lt;sys/sem.h&gt;<br />
#include &lt;sys/shm.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
#include &lt;errno.h&gt;<br />
#include &lt;string.h&gt;<br />
<br />
# if defined(__GNU_LIBRARY___)&amp;&amp;! defined(__SEM_SEMUN_UNDEFINED)<br />
#else<br />
&nbsp;&nbsp;&nbsp; union semun{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int val;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; struct semid_ds *buf;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; unsigned short int *array;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; struct seminfo *__buf;<br />
&nbsp;&nbsp;&nbsp; };<br />
#endif<br />
<br />
int semheld = 0;<br />
int master = 0;<br />
int id = 0;<br />
<br />
void release(int id);<br />
void request(int id);<br />
void delete(void);<br />
<br />
int main(int argc,char *argv[])<br />
{<br />
&nbsp;&nbsp;&nbsp; union semun sunion;<br />
&nbsp;&nbsp;&nbsp; if(argc&lt;2)//如果不带参数，就创建一个新的信号量<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; id=semget(IPC_PRIVATE,1,SHM_R|SHM_W);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(id!=-1)<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; atexit(&amp;delete);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sunion.val=1;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(semctl(id,0,SETVAL,sunion)==-1)<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Semctl failed:%s\n&quot;,strerror(errno));<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(255);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; master=1;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; id=atoi(argv[1]);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Using exiting semaphore %d.\n&quot;,id);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; if(id==-1)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Semaphore request failed:%s.\n&quot;,strerror(errno));<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 0;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Successfully allocated semaphore id\033[32m %d\n\033[m&quot;,id);<br />
&nbsp;&nbsp;&nbsp; while(1)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int selection;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;\nStatus:%d resources held by this process.\n&quot;,semheld);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Menu:\n&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;1.release a resource\n&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;2.Request a resource\n&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;3.Exit this process\n&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; scanf(&quot;%d&quot;,&amp;selection);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; switch(selection)<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 1: release(id);break;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 2: request(id);break;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 3:exit(0);break;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return 0;<br />
}<br />
void release(int id)<br />
{<br />
&nbsp;&nbsp;&nbsp; struct sembuf sb;<br />
&nbsp;&nbsp;&nbsp; if(semheld &lt; 1)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;\033[31mI don't have any resources:nothing to release.\n\033[m&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; //信号量的最大值为1,并且对进程来说，这表明资源正在使用中，要使用必须等待<br />
&nbsp;&nbsp;&nbsp; sb.sem_num=0;//指定信号量中要操作的信号量：0表示第一个<br />
&nbsp;&nbsp;&nbsp; sb.sem_op =1;//操作指定要完成的操作，正数表示信号量值应该增加，负数从信号量值中减去相应的值，表示资源的消耗<br />
&nbsp;&nbsp;&nbsp; sb.sem_flg=0;//操作标志:SEM_UNDO进程在没有释放消耗的资源退出，则这些资源将被操作系统释放。IPC_NOWAIT：函数调用将是非阻塞的<br />
&nbsp;&nbsp;&nbsp; semop(id,&amp;sb,1);<br />
&nbsp;&nbsp;&nbsp; semheld--;<br />
&nbsp;&nbsp;&nbsp; printf(&quot;\033[32mResource released.\n\033[m&quot;);<br />
}<br />
void request(int id)<br />
{<br />
&nbsp;&nbsp;&nbsp; struct sembuf sb;<br />
&nbsp;&nbsp;&nbsp; if(semheld&gt;0)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;\033[31mI already hold the resource;not requesting another one.\n\033[m&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return ;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; sb.sem_num=0;<br />
&nbsp;&nbsp;&nbsp; sb.sem_op=-1;<br />
&nbsp;&nbsp;&nbsp; sb.sem_flg=0;<br />
&nbsp;&nbsp;&nbsp; printf(&quot;\033[32mRequeseing resource ...\033[m&quot;);<br />
&nbsp;&nbsp;&nbsp; fflush(stdout);<br />
&nbsp;&nbsp;&nbsp; semop(id,&amp;sb,1);<br />
&nbsp;&nbsp;&nbsp; semheld++;<br />
&nbsp;&nbsp;&nbsp; printf(&quot;\033[32mdone.\n\033[m&quot;);<br />
}<br />
void delete(void)<br />
{<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Master exiting:deleting semaphore.\n&quot;);<br />
&nbsp;&nbsp;&nbsp; if(semctl(id,0,IPC_RMID,0)==-1)<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Error releasing semaphore.\n&quot;);<br />
}<br />
<br />
内存共享：<br />
申请一段内存，并向里面写数据：<br />
#include &lt;sys/shm.h&gt;<br />
#include &lt;sys/types.h&gt;<br />
#include &lt;unistd.h&gt;<br />
#include &lt;string.h&gt;<br />
#include &lt;stdio.h&gt;<br />
typedef struct{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char name[20];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int age;<br />
} info;<br />
int main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int id,i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; key_t key;<br />
&nbsp;&nbsp;&nbsp; char *str=&quot;Hello world!&quot;;<br />
&nbsp;&nbsp;&nbsp; int len=strlen(str);<br />
&nbsp;&nbsp;&nbsp; info *info_p;<br />
&nbsp;&nbsp;&nbsp; char* name = &quot;/dev/null&quot;;<br />
&nbsp;&nbsp;&nbsp; key = ftok(name,0);/*先用ftok创建一个key,再调用shmget，创建一块共享内存区域*/<br />
&nbsp;&nbsp;&nbsp; if(key==-1)<br />
&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; perror(&quot;ftok&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 1;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; id=shmget(key,4096,IPC_CREAT);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if(id==-1)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; perror(&quot;shmget&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 1;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; info_p=(info*)shmat(id,NULL,0);/*将这块共享内存区附加到自己的内存段*/<br />
&nbsp;&nbsp;&nbsp; for(i = 0;i&lt;len;i++)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; memcpy((*(info_p+i)).name,&amp;str[i],1);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (*(info_p)).age=20;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; info_p-&gt;age=20;<br />
&nbsp;&nbsp;&nbsp; if(shmdt(info_p)==-1)/*写数据完毕，将其从自己的内存段中&ldquo;删除&rdquo;出去*/<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; perror(&quot;shmdt&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 1;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return 0;<br />
}<br />
<br />
读共享部分数据：<br />
#include &lt;sys/ipc.h&gt;<br />
#include &lt;sys/shm.h&gt;<br />
#include &lt;sys/types.h&gt;<br />
#include &lt;unistd.h&gt;<br />
#include &lt;string.h&gt;<br />
#include &lt;stdio.h&gt;<br />
typedef struct{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char name[100];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int age;<br />
} people;<br />
main(int argc, char** argv)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int shm_id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; key_t key;<br />
&nbsp;&nbsp;&nbsp; char *str=&quot;Hello world!&quot;;<br />
&nbsp;&nbsp;&nbsp; int len=strlen(str);<br />
&nbsp;&nbsp;&nbsp; char buf[len];<br />
&nbsp;&nbsp;&nbsp; strcpy(buf,str);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; people *p_map;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char* name = &quot;/dev/null&quot;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; key = ftok(name,0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(key==-1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror(&quot;ftok error&quot;);<br />
/*先用ftok创建一个key,再调用shmget，创建一块共享内存区域*/<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shm_id=shmget(key,4096,IPC_CREAT);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(shm_id==-1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror(&quot;shmget error&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
/*将这块共享内存区附加到自己的内存段*/<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p_map=(people*)shmat(shm_id,NULL,0);<br />
&nbsp;&nbsp;&nbsp; memset(buf,0,len);<br />
&nbsp;&nbsp;&nbsp; int i;<br />
&nbsp;&nbsp;&nbsp; for(i=0;i&lt;len;i++)<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcat(buf,(*(p_map+i)).name);<br />
&nbsp;&nbsp;&nbsp; printf(&quot;%s\n&quot;,buf);<br />
&nbsp;&nbsp;&nbsp; printf(&quot;%d\n&quot;,p_map-&gt;age);<br />
/*写数据完毕，将其从自己的内存段中&ldquo;删除&rdquo;出去*/<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(shmdt(p_map)==-1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perror(&quot; detach error &quot;);<br />
}<br />
<br />
<br />
]]></description>
		</item>
		    
		
		<item>
			<title>《linux编程宝典》笔记3</title>
			<link>http://fitren.blog.sohu.com/36650441.html</link>
			<comments>http://fitren.blog.sohu.com/36650441.html#comment</comments>
			<dc:creator>fitren</dc:creator>
			<pubDate>Fri, 9 Mar 2007 10:34:21 +0800</pubDate>
			<category>技术类</category>
			<guid>http://fitren.blog.sohu.com/36650441.html</guid>
			<description><![CDATA[用popen实现shell管道<br />
#include &lt;stdio.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
#include &lt;unistd.h&gt;<br />
int main()<br />
{<br />
&nbsp;&nbsp; &nbsp;FILE *fp_r,*fp_w;<br />
&nbsp;&nbsp; &nbsp;fp_r=popen(&quot;ls|grep fork&quot;,&quot;r&quot;);<br />
&nbsp;&nbsp; &nbsp;fp_w=popen(&quot;sed 's/fork/FORK/g'&quot;,&quot;w&quot;);<br />
&nbsp;&nbsp; &nbsp;char buf_r[128];<br />
&nbsp;&nbsp; &nbsp;while(fgets(buf_r,sizeof(buf_r),fp_r))<br />
&nbsp;&nbsp; &nbsp;{<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;fputs(buf_r,fp_w);<br />
&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;pclose(fp_r);<br />
&nbsp;&nbsp; &nbsp;pclose(fp_w);&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;return 0;<br />
}<br />
<br />
用pipe实现父子进程之间通信，主要是父子进程为pipe的两端，一端写，一端读<br />
#include &lt;stdio.h&gt;<br />
#include &lt;unistd.h&gt;<br />
#include &lt;string.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
#include &lt;sys/wait.h&gt;<br />
<br />
int main()<br />
{<br />
&nbsp;&nbsp;&nbsp; int dp;<br />
&nbsp;&nbsp;&nbsp; int fd[2];&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; char *buf;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; buf=malloc(100);<br />
&nbsp;&nbsp;&nbsp; int pid;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; memset(buf,0,sizeof(buf)); <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; int flag=1;<br />
&nbsp;&nbsp;&nbsp; if(pipe(fd)==0)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pid=fork();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(pid==0)<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; flag++;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; char *buf_w=malloc(100);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sprintf(buf_w,&quot;%d&quot;,flag);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
write(fd[1],buf_w,strlen(buf_w));&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Write \&quot;%s\&quot; to the parent!\n&quot;,buf_w);<br />
//&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _exit(0);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; read(fd[0],buf,10);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Read \&quot;%s\&quot; from the child!\n&quot;,buf); <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;flag=%d\n&quot;,flag=atoi(buf));<br />
//&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _exit(0); <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return 0;<br />
}<br />
<br />
用wait让父进程等待子进程完成之后再执行<br />
#include &lt;stdio.h&gt;<br />
#include &lt;signal.h&gt;<br />
#include &lt;sys/wait.h&gt;<br />
int main()<br />
{<br />
&nbsp;&nbsp;&nbsp; int pid;<br />
&nbsp;&nbsp;&nbsp; pid=fork();<br />
&nbsp;&nbsp;&nbsp; if(pid==0)<br />
&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;The child will sleep 5 seconds!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sleep(5);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; waitpid(-1,NULL,0);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;The parent will sleep 5 seconds!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sleep(5);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;The parent is exiting now!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return 0;<br />
}<br />
<br />
va_list ，可变参数函数用法<br />
#include &lt;stdio.h&gt;<br />
#include &lt;unistd.h&gt;<br />
#include &lt;stdarg.h&gt;<br />
#include &lt;time.h&gt;<br />
#include &lt;sys/types.h&gt;<br />
#include &lt;sys/wait.h&gt;<br />
#include &lt;signal.h&gt;<br />
<br />
int tprintf(const char *fmt, ...);<br />
void realsleep(int seconds);<br />
void waitchildren(int signum);<br />
int main(void)<br />
{<br />
&nbsp;&nbsp;&nbsp; pid_t pid;<br />
&nbsp;&nbsp;&nbsp; pid=fork();<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if(pid==0)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tprintf(&quot;Hello from child process!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tprintf(&quot;The child is sleep for 5 seconds.\n&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; realsleep(5);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tprintf(&quot;The child is exiting now!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(pid!=-1)<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; signal(SIGCHLD,(void *)waitchildren);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tprintf(&quot;Hello from the parent,pid:%d.\n&quot;,getpid());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tprintf(&quot;The parent has forked process %d.\n&quot;,pid);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; waitpid(pid,NULL,0);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tprintf(&quot;The child has stopped,Sleeping for 5 seconds.\n&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; realsleep(5);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tprintf(&quot;The parent is exiting now.\n&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tprintf(&quot;There is an error with fork!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return 0;<br />
}<br />
int tprintf(const char *fmt, ...)<br />
{<br />
&nbsp;&nbsp;&nbsp; va_list args;<br />
&nbsp;&nbsp;&nbsp; struct tm *tstruct;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; time_t tsec;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; tsec=time(NULL);<br />
&nbsp;&nbsp;&nbsp; tstruct=localtime(&amp;tsec);<br />
&nbsp;&nbsp;&nbsp; printf(&quot;%02d:%02d:%02d %05d|&quot;,<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tstruct-&gt;tm_hour,<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tstruct-&gt;tm_min,<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tstruct-&gt;tm_sec,<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; getpid());<br />
&nbsp;&nbsp;&nbsp; va_start(args,fmt);//读取不定参数的固定参数后的第一个参数<br />
&nbsp;&nbsp;&nbsp; vprintf(fmt,args);//把参数中变量的值打印出来，eg.&rdquo;Hello from the
parent,pid:%d.\n&ldquo;中把%d替换成实际值，如果用printf,则打印出来的是&rdquo;Hello from the
parent,pid:%d.\n&ldquo;没有替换成具体的值<br />
&nbsp;&nbsp;&nbsp; va_end(args);<br />
&nbsp;&nbsp;&nbsp; return 0;<br />
}<br />
void waitchildren(int signum)<br />
{<br />
&nbsp;&nbsp;&nbsp; pid_t pid;<br />
<br />
&nbsp;&nbsp;&nbsp; while ((pid=waitpid(-1,NULL,WNOHANG))&gt;0)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tprintf(&quot;Caught the exit of child process %d.\n&quot;,pid);<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
void realsleep(int seconds)<br />
{<br />
&nbsp;&nbsp;&nbsp; while(seconds)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; seconds=sleep(seconds);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(seconds)<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; tprintf(&quot;Restarting interrupted sleep for %d more seconds,\n&quot;,seconds);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
获取文件信息：<br />
<br />
#include &lt;stdio.h&gt;<br />
#include &lt;sys/stat.h&gt;<br />
#include &lt;unistd.h&gt;<br />
#include &lt;sys/types.h&gt;<br />
int main(int argc,char *argv[])<br />
{<br />
&nbsp;&nbsp;&nbsp; if(argc!=2)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Usage:%s filename\n&quot;,argv[0]);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _exit(0);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; printf(&quot;The information for file %s:\n&quot;,argv[1]);<br />
<br />
&nbsp;&nbsp;&nbsp; struct stat sbuf;<br />
&nbsp;&nbsp;&nbsp; if(lstat(argv[1],&amp;sbuf)== -1)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;lstat error!\n&quot;);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _exit(0);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Device:%d\n&quot;,sbuf.st_dev);<br />
&nbsp;&nbsp;&nbsp; if(S_ISREG(sbuf.st_mode))<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;Reagular file:Yes\n&quot;);<br />
&nbsp;&nbsp;&nbsp; else printf(&quot;Reagular file:No\n&quot;);<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Owner uid:%d\n&quot;,sbuf.st_uid);<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Permisson:%o\n&quot;,sbuf.st_mode&amp;(S_IRWXU|S_IRWXG|S_IRWXO));<br />
&nbsp;&nbsp;&nbsp; printf(&quot;Other execute permision:%o\n&quot;,sbuf.st_mode&amp;S_IXOTH);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return 0;<br />
}<br />
<br />
setuid:<br />
<br />
#include &lt;stdio.h&gt;<br />
#include &lt;sys/types.h&gt;<br />
#include &lt;unistd.h&gt;<br />
#include &lt;sys/stat.h&gt;<br />
#include &lt;fcntl.h&gt;<br />
<br />
int try_open()<br />
{<br />
&nbsp;&nbsp;&nbsp; char *filename=&quot;/root/xorg.conf.bak&quot;;<br />
&nbsp;&nbsp;&nbsp; int fd=open(filenam