summaryrefslogtreecommitdiff
path: root/pod/perlipc.pod
blob: 5a43660fb25c2b4527f37747c9ac2f8620008a51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
=head1 NAME

perlipc - Perl interprocess communication

=head1 DESCRIPTION

The IPC facilities of Perl are built on the Berkeley socket mechanism.
If you don't have sockets, you can ignore this section.  The calls have
the same names as the corresponding system calls, but the arguments
tend to differ, for two reasons.  First, Perl file handles work
differently than C file descriptors.  Second, Perl already knows the
length of its strings, so you don't need to pass that information.

=head2 Client/Server Communication

Here's a sample TCP client.

    ($them,$port) = @ARGV;
    $port = 2345 unless $port;
    $them = 'localhost' unless $them;

    $SIG{'INT'} = 'dokill';
    sub dokill { kill 9,$child if $child; }

    use Socket;

    $sockaddr = 'S n a4 x8';
    chop($hostname = `hostname`);

    ($name, $aliases, $proto) = getprotobyname('tcp');
    ($name, $aliases, $port) = getservbyname($port, 'tcp')
	unless $port =~ /^\d+$/;
    ($name, $aliases, $type, $len, $thisaddr) =
		    gethostbyname($hostname);
    ($name, $aliases, $type, $len, $thataddr) = gethostbyname($them);

    $this = pack($sockaddr, AF_INET, 0, $thisaddr);
    $that = pack($sockaddr, AF_INET, $port, $thataddr);

    socket(S, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
    bind(S, $this) || die "bind: $!";
    connect(S, $that) || die "connect: $!";

    select(S); $| = 1; select(stdout);

    if ($child = fork) {
	while (<>) {
	    print S;
	}
	sleep 3;
	do dokill();
    }
    else {
	while (<S>) {
	    print;
	}
    }

And here's a server:

    ($port) = @ARGV;
    $port = 2345 unless $port;

    use Socket;

    $sockaddr = 'S n a4 x8';

    ($name, $aliases, $proto) = getprotobyname('tcp');
    ($name, $aliases, $port) = getservbyname($port, 'tcp')
	unless $port =~ /^\d+$/;

    $this = pack($sockaddr, AF_INET, $port, "\0\0\0\0");

    select(NS); $| = 1; select(stdout);

    socket(S, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
    bind(S, $this) || die "bind: $!";
    listen(S, 5) || die "connect: $!";

    select(S); $| = 1; select(stdout);

    for (;;) {
	print "Listening again\n";
	($addr = accept(NS,S)) || die $!;
	print "accept ok\n";

	($af,$port,$inetaddr) = unpack($sockaddr,$addr);
	@inetaddr = unpack('C4',$inetaddr);
	print "$af $port @inetaddr\n";

	while (<NS>) {
	    print;
	    print NS;
	}
    }

=head2 SysV IPC

Here's a small example showing shared memory usage:

    $IPC_PRIVATE = 0;
    $IPC_RMID = 0;
    $size = 2000;
    $key = shmget($IPC_PRIVATE, $size , 0777 );
    die if !defined($key);

    $message = "Message #1";
    shmwrite($key, $message, 0, 60 ) || die "$!";
    shmread($key,$buff,0,60) || die "$!";

    print $buff,"\n";

    print "deleting $key\n";
    shmctl($key ,$IPC_RMID, 0) || die "$!";

Here's an example of a semaphore:

    $IPC_KEY = 1234;
    $IPC_RMID = 0;
    $IPC_CREATE = 0001000;
    $key = semget($IPC_KEY, $nsems , 0666 | $IPC_CREATE );
    die if !defined($key);
    print "$key\n";

Put this code in a separate file to be run in more that one process
Call the file F<take>:

    # create a semaphore

    $IPC_KEY = 1234;
    $key = semget($IPC_KEY,  0 , 0 );
    die if !defined($key);

    $semnum = 0;
    $semflag = 0;

    # 'take' semaphore
    # wait for semaphore to be zero
    $semop = 0;
    $opstring1 = pack("sss", $semnum, $semop, $semflag);

    # Increment the semaphore count
    $semop = 1;
    $opstring2 = pack("sss", $semnum, $semop,  $semflag);
    $opstring = $opstring1 . $opstring2;

    semop($key,$opstring) || die "$!";

Put this code in a separate file to be run in more that one process
Call this file F<give>:

    #'give' the semaphore
    # run this in the original process and you will see
    # that the second process continues

    $IPC_KEY = 1234;
    $key = semget($IPC_KEY, 0, 0);
    die if !defined($key);

    $semnum = 0;
    $semflag = 0;

    # Decrement the semaphore count
    $semop = -1;
    $opstring = pack("sss", $semnum, $semop, $semflag);

    semop($key,$opstring) || die "$!";